Java 具有隐式向下转换的调用方法
我有一个定义为Java 具有隐式向下转换的调用方法,java,oop,design-patterns,Java,Oop,Design Patterns,我有一个定义为 List<ParentClass> parentClassList; 等等。。。我现在实际上有5个儿童班 我想做的是调用另一个类中的方法,覆盖其参数,因此: public void doSomething(ChildClassOne arg) {...} public void doSomething(ChildClassTwo arg) {...} 但是如果列表的类型是父类,我就不能这样做 doSomething(parentClassList.get(0));
List<ParentClass> parentClassList;
等等。。。我现在实际上有5个儿童班
我想做的是调用另一个类中的方法,覆盖其参数,因此:
public void doSomething(ChildClassOne arg) {...}
public void doSomething(ChildClassTwo arg) {...}
但是如果列表的类型是父类,我就不能这样做
doSomething(parentClassList.get(0));
基本上,我需要根据孩子的类型执行不同的操作,并且我需要访问特定孩子内部的所有方法。不同的子类有不同的方法,它们只有一个共同的方法。在
ParentClass
中定义一个抽象的emthoddoSomthing()
,在每个子类中实现它如下:
class ChildClassOne {
void doSomething() {
instanceOfSomeOtherClass.doSomething(this); // will call the correct method
}
}
其他类将为每个子类提供方法:
class SomeOtherClass {
void doSomething(ChildClassOne o) {};
void doSomething(ChildClassTwo o) {};
void doSomething(ChildClassThree o) {};
...
}
您可以从以下方面了解此方法:
如果将代码从
其他类
移动到子类
中,可能会更简单。在父类
中定义一个抽象的emthoddoSomthing()
,并在每个子类中实现它如下:
class ChildClassOne {
void doSomething() {
instanceOfSomeOtherClass.doSomething(this); // will call the correct method
}
}
其他类将为每个子类提供方法:
class SomeOtherClass {
void doSomething(ChildClassOne o) {};
void doSomething(ChildClassTwo o) {};
void doSomething(ChildClassThree o) {};
...
}
您可以从以下方面了解此方法:
如果将代码从
其他类
移动到子类
中,可能会更简单。在这种情况下,一种称为
interface Visitor {
void visitChildOne(ChildOne child);
void visitChildTwo(ChildTwo child);
void visitChildThree(ChildThree child);
}
abstract class ParentClass {
public abstract void accept(Visitor v);
...
}
class ChildClassOne extends ParentClass {
@Override
public void accept(Visitor v) { v.visitChildOne(this); }
}
class ChildClassTwo extends ParentClass {
@Override
public void accept(Visitor v) { v.visitChildTwo(this); }
}
class ChildClassThree extends ParentClass {
@Override
public void accept(Visitor v) { v.visitChildThree(this); }
}
当您需要执行一些任务,根据子项的类型执行不同的操作时,请提供Visitor
界面的实现,并将其传递给希望处理的每个子项的accept
:
Visitor v = new Visitor() {
@Override
public void visitChildOne(ChildOne child) {
System.out.println("Visiting child type 1");
String someProperty = child.getPropertySpecificToChildOne();
}
@Override
public void visitChildTwo(ChildTwo child) {
System.out.println("Visiting child type 2");
int someProperty = child.getPropertySpecificToChildTwo();
}
@Override
public void visitChildThree(ChildThree child) {
System.out.println("Visiting child type 3");
}
};
for (Parent p: parentClassList) {
p.accept(v);
}
在这种情况下,一种称为双分派的技术变得非常方便:
interface Visitor {
void visitChildOne(ChildOne child);
void visitChildTwo(ChildTwo child);
void visitChildThree(ChildThree child);
}
abstract class ParentClass {
public abstract void accept(Visitor v);
...
}
class ChildClassOne extends ParentClass {
@Override
public void accept(Visitor v) { v.visitChildOne(this); }
}
class ChildClassTwo extends ParentClass {
@Override
public void accept(Visitor v) { v.visitChildTwo(this); }
}
class ChildClassThree extends ParentClass {
@Override
public void accept(Visitor v) { v.visitChildThree(this); }
}
当您需要执行一些任务,根据子项的类型执行不同的操作时,请提供Visitor
界面的实现,并将其传递给希望处理的每个子项的accept
:
Visitor v = new Visitor() {
@Override
public void visitChildOne(ChildOne child) {
System.out.println("Visiting child type 1");
String someProperty = child.getPropertySpecificToChildOne();
}
@Override
public void visitChildTwo(ChildTwo child) {
System.out.println("Visiting child type 2");
int someProperty = child.getPropertySpecificToChildTwo();
}
@Override
public void visitChildThree(ChildThree child) {
System.out.println("Visiting child type 3");
}
};
for (Parent p: parentClassList) {
p.accept(v);
}
基本上,我需要根据孩子的类型执行不同的操作,并且我需要访问特定孩子内部的所有方法
在这种情况下,您想要实现的行为属于这个专用类
您可以向基类添加另一个(抽象)方法签名,该基类在提供依赖类型行为的子类中实现
基本上,我需要根据孩子的类型执行不同的操作,并且我需要访问特定孩子内部的所有方法
在这种情况下,您想要实现的行为属于这个专用类
您可以向基类添加另一个(抽象)方法签名,该方法签名在提供类型相关行为的子类中实现。而不是
doSomething(ChildClassOne arg)
,在每个子类中执行parentClass.doSomething()
,并重写doSomething()
。这就是多态性的原理。泛型基本上是不协变的。不能更改泛型参数的类型。如果是父类,你必须把它取出来,因为那是你在里面说的,你不能改变它。你说的“覆盖”是什么意思?不是doSomething(ChildClassOne arg)
,而是在每个子类中做ParentClass.doSomething()
,重写doSomething()
。这就是多态性的原理。泛型基本上是不协变的。不能更改泛型参数的类型。如果是父类,你必须把它取出来,因为这就是你在里面说的,你不能改变它。你说的“覆盖”是什么意思?这基本上就是答案。您应该在doSomething()
方法中添加它,然后将其参数类型更改为ParentClass
@markspace否,该模式的优点在于SomeOtherClass
中的每个子类型都有一个特定的方法,因此,您不必执行instanceof
或特殊行为可以在子类doSomething()
…@TimothyTruckle:D中实现,这是我本人第二次添加的最后一条建议。这基本上就是答案。您应该在doSomething()
方法中添加它,然后将其参数类型更改为ParentClass
@markspace否,该模式的优点在于SomeOtherClass
中的每个子类型都有一个特定的方法,因此,您不必执行instanceof
或特殊行为可以在子类doSomething()
…@TimothyTruckle:D中实现,这是我自己第二次添加的最后一个建议。我认为这在OPs示例中根本不起作用。你能告诉我们这是怎么回事吗?@markspace这一模式是为了做OP想做的事情而发明的。在OP的情况下,没有任何东西会阻止此模式工作。如果需要,此模式的一个很好的变体是使访问者泛型(visitor),使所有visit()方法返回T,并使accept()方法泛型并返回T,也是。@markspace我觉得奇怪的是,你在另一个答案中立即发现了这种模式,doSomething
是重载的,并且没有想到它在我的版本中会起作用,因为我的版本消除了重载,使人们更容易理解这种模式,而不必事先接触它。你得到了我的支持:-)。我还发现,当重载和泛型不存在时,更容易理解模式。但对于其他读者来说,我认为这条评论可能有用。我认为这在OPs示例中根本不起作用。你能告诉我们这是怎么回事吗?@markspace这一模式是为了做OP想做的事情而发明的。在OP的情况下,没有任何东西会阻止此模式工作。如果需要,此模式的一个很好的变体是使访问者成为泛型(visitor),使所有visit()方法返回T,并使accept()成为