Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中向下转换的良好实践_Java - Fatal编程技术网

java中向下转换的良好实践

java中向下转换的良好实践,java,Java,我有一套手术。每个操作由两个步骤组成。因此,我有一个执行这两个步骤的基类,所有操作都扩展了这个基类,并提供了这两个步骤的实际实现。前 class Base { Step1 step1; Step2 step2; B execute() { A a = step1.perform(); B b = step2.perform(a); } //Set methods... } 在这里,Step1和Step2是接口,人们可以

我有一套手术。每个操作由两个步骤组成。因此,我有一个执行这两个步骤的基类,所有操作都扩展了这个基类,并提供了这两个步骤的实际实现。前

class Base {
    Step1 step1;
    Step2 step2;

    B execute() {
        A a = step1.perform();
        B b = step2.perform(a);
    }

    //Set methods...
}
在这里,Step1和Step2是接口,人们可以更改实现,让它们做不同的事情

我有以下问题:

  • step2的每个实现都将A的实例作为输入,它也可以包含A的派生类型。在这种情况下,可以做一个向下预测吗?或者有更好的方法来实现这一点吗
  • 步骤2的某些实现可能不会返回任何值。如果我们只有一个空类用于类型层次结构,而其他类扩展了这个类,这样可以吗
问题1 是的,没关系。扩展类A或实现接口A的每个类(无论A是什么)都将是“A的实例”。所以,将它传递给一个需要类型为a的对象的方法是完全可以的。无需担心。这就是您应该如何使用接口和继承。同一个超级类有不同类型的“专门化”

问题2 这是API设计的问题。如果希望此方法返回null,可以这样做。但是你应该把它记录得非常好

Java8中的一个非常新的可能性是所谓的选项。如果一个方法可能返回null,并且您希望强制程序员记住这一点,那么可以使用它们。这将是最干净(也是最推荐的)的方式。您可以在中找到示例和说明。基本上,您会说类
Step2
的方法
perform
将返回可选的,而不是类型:

interface Setp2 {
    public Optional<B> perform(A a);
}

// the optional will wrap the actual result which could be null
// since Java 8
Optional<B> b = step2.perform(a);
接口Setp2{
公共自选表演(A);
}
//可选项将包装可能为空的实际结果
//自Java8以来
可选b=步骤2.执行(a);

听起来您应该使用泛型:

interface Step1<T extends A> {
    T perform(T a);
}
interface Step2<T extends A, U extends B> {
    U perform(T a);
}

class Base<T extends A, U extends B>>{
Step1<T> step1;
Step2<T, U> step2;

B execute() {
    T a = step1.perform();
    U b = step2.perform(a);
}

//Set methods...
接口步骤1{
T执行(ta);
}
接口步骤2{
U执行(T a);
}
班级基数>{
步骤1步骤1;
步骤2步骤2;
B执行(){
T a=步骤1.执行();
U b=步骤2.执行(a);
}
//设置方法。。。
}


关于返回“nothing”,最好的方法是返回
null

Base的子类是否总是使用A和/或B的某个特定子类?嗯,我真的不太理解这个问题。也许您可以展示更多的代码或更深入地解释它。或许泛型可以帮助您实现一些安全类型转换,但我真的不知道。我想我需要看一个更完整的代码示例。我不太明白你的描述。是的,step1的每个实现都会返回一个amd的子类step2的每个实现都会输入a的某个子类。因此base的每个子类都会使用a