Java 将类型作为参数传递给需要子类型的函数

Java Passing Type as parameter into function expecting subtype

我是 Java 的新人,我尝试制作一些非常简单的 java 应用程序。在我的尝试中,我遇到了泛化问题。我有一个 Person 对象的列表。 可以是父亲母亲

然后,我有几个同名的方法 eat(...) 但它们的输入参数不同。这些方法不是 Person class 的一部分。其中一种方法接受 Mother 作为参数,另一种方法接受 Father

问题是如何动态决定在 Person 列表上调用哪个方法。当我尝试遍历列表并调用 o.eat(iterator) 它提示编译器错误,因为迭代器的类型是 Person 但我的eat 方法需要 MotherFather 作为参数。编译器不知道我有针对每种类型的 Person

的方法

到目前为止,我已经用 if 语句解决了我的问题,在该语句中我通过 GetType() 比较了 class 类型MotherFather 的方法,如果它等于我可以将 Person 转换为适当的类型。

代码如下所示:

  if (person.getClass().equals(Father.class)) {
            theView.eat((Father) person);
        }


  if (person.getClass().equals(Mother.class)) {
            theView.eat((Mother) person);
        }

吃法如下:

 public void eat(Mother m){
    textArea.append(m.breakfast);
    textArea.append(m.lunch);
    textArea.append(m.dinner);
 }

lunch dinner 和 breakfast 只是一些表示此人在做什么的字符串

person 是代码是遍历 Person 对象列表的迭代器

是否有更好的解决方案可以使流程自动化?

提前致谢。

使用多态性:

public interface Person{
    void eat();
}

public class Mother implements Person{

    @Override
    public void eat()
    {
        //the code inside eat(Mother) goes here
    }

}

public class Father implements Person{

    @Override
    public void eat()
    {
        //the code inside eat(Father) goes here
    }

}

然后,只需对 Person 列表中的每个对象调用 eat 方法即可:

for(final Person person: personList){
    person.eat();
}

我认为你需要访问者模式,因为你在这里说的

The question is how to dynamically decide which method to invoke on list of Person.

https://sourcemaking.com/design_patterns/visitor/java/2

这可以帮助您决定在 运行 时间

动态采用哪条路线

来自维基百科:https://en.wikipedia.org/wiki/Double_dispatch

double dispatch is a special form of multiple dispatch, and a mechanism that dispatches a function call to different concrete functions depending on the runtime types of two objects involved in the call.

Then, i have couple of methods with same name eat(...) but they differ in input parameters

如果你的 class 使用不同的 eat 方法实现如下:

public class TheView<T extends Person> {
    public void eat(T t) {
         textArea.append(t.getMeals());
    }
}

现在你的迭代方法可以实现如下:

public <T> void yourMethod(List<? extends Person> personList) {
    for (Person p : personList) {
         theView.eat(p);
    }
}

您的列表可以包含任意数量的 FatherMother 对象,前提是它们实现/扩展 Person class,如

public abstract class Person {
    private String breakfast;
    private String lunch;
    // ... other fields

    public abstract void getMeals();

    public String getBreakfast() { return breakfast; }
    // ... other getters
}

public class Father extends Person {
     @Override
     public void getMeals() {
         // implement Father-specific code here
     }
}

public class Mother extends Person {

     @Override
     public String getMeals() {
        StrngBuilder sb = new StringBuilder() ;

        sb.append(getBreakfast());
        sb.append(getLunch());
        sb.append(getDinner());

        return sb.toString();
    }
}