Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.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_Oop_Design Patterns - Fatal编程技术网

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
中定义一个抽象的emthod
doSomthing()
,在每个子类中实现它如下:

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) {};
    ...
}
您可以从以下方面了解此方法:


如果将代码从
其他类
移动到
子类
中,可能会更简单。

父类
中定义一个抽象的emthod
doSomthing()
,并在每个子类中实现它如下:

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()成为