代码之家  ›  专栏  ›  技术社区  ›  user7794336

Java中从列表路由方法调用的最佳方法

  •  1
  • user7794336  · 技术社区  · 7 年前

    根据列表中不同的对象类型调用类的不同方法的最佳方式是什么?

    常见示例:

    public class Dog extends Animals{
      ...
      public void say(){
        System.out("i'm a dog");
    }
    
    public class Cat extends Animals{
      ...
      public void say(){
        System.out("i'm a cat");
    }
    
    public class OtherClass {
      public void route(){
        List<Animals> aList = new ArrayList<>();
        a.add(new Dog());
        a.add(new Cat());
        for(Animals a:aList)
         methodOverloaded(a); ---> that's the point <---
      }
      public methodOverloaded(Dog d){
        d.say();
      }
    
      public methodOverloaded(Cat c){
        c.say();
     }
    }
    

    当然,隐喻的目的是印刷 I'm a dog I'm a cat 第二次运行时 methodOverloaded() .

    我试过了

    • 访客模式
    • instanceOf()

    编辑:我非常希望调用示例的重载方法 OtherClass

    4 回复  |  直到 7 年前
        1
  •  2
  •   J-Alex Dorota Przeniosło    7 年前

    最好的方法是在Animal中定义抽象方法,并在子类中重写它。这就是多态性的工作原理。

    不需要过载。

    public abstract class Animal {
        public abstract void say();
    }
    
    public class Dog extends Animal {
    
        @Override
        public void say() {
            System.out.println("Bark");
        }
    }
    
    public class Cat extends Animal {
    
        @Override
        public void say() {
            System.out.println("Meow");
        }
    }
    

    :

    public class Main() {
        public static void main(String[] args) {
            List<Animals> aList = new ArrayList<>();
            a.add(new Dog());
            a.add(new Cat());
            for (Animals a : aList)
                a.say();
        }
    }
    

    输出 :

    Bark
    Meow
    

    ____更新_1

    我想补充一些意见,为什么重载这些方法不是一个好主意。

    public methodOverloaded(Animal a) {
        a.say();
    }
    

    但它不会像你期望的那样工作。它会呼叫 public methodOverloaded(Animal a) List .

    对于循环的所有迭代,参数的编译时类型为 Animal 动物 ,唯一适用的过载是第三种过载。

    这可以通过以下方式解决:

    public methodOverloaded(Animal a) {
        if (a instanceof Cat) ? "Meow" : 
           (a instanceof Dog) ? "Bark" : "Unknown Animal"
    }
    

    此外,一个安全、保守的政策是永远不要出口两个过载

    例如 ArrayList int Collection 。很难想象在任何情况下会调用这两个构造函数中的哪一个。

        2
  •  0
  •   haraldfw Nicolas    7 年前

    你需要在Animal中定义方法,并将其抽象化

    abstract class Animal {
        public abstract void say();
    }
    

    a.say()

        3
  •  0
  •   Blasanka    7 年前

    你可以这样做:

    for(Animals a:aList){
        if(a instanceof Dog){
            methodOverloaded((Dog) a);
        }else if(a instanceof Cat){
            methodOverloaded((Cat) a);
        }
    }
    

    但是根据你在问题中描述的场景,@J-Alex answer是一个好方法。

        4
  •  0
  •   hi.nitish    7 年前

    我可以告诉你“工厂设计模式”在这里是如何合适的。 定义主类如下:

    public abstract class Animal {
        public abstract void say();
    }
    
    
    public class Dog extends Animal {
    
        @Override
        public void say() {
            System.out.println("Bark");
        }
    }
    public class Cat extends Animal {
    
        @Override
        public void say() {
            System.out.println("Meow");
        }
    }
    
    public class FactoryClass{
    
    public static Animal getCorrectAnimal(String type){
     if("Cat".equalsIgnoreCase(type)) return new Cat();
     else if ("Dog".equalsIgnoreCase(type)) return new Dog();
    
    return null;
    }
    
    }
    
    
    public class TestFactoryClass {
    
        public static void main(String[] args) {
            Animal an = ComputerFactory.getCorrectAnimal("Cat");
            List<Animals> aList = new ArrayList<>();
            a.add(FactoryClass.getCorrectAnimal("Dog"));
            a.add(FactoryClass.getCorrectAnimal("Cat"));
            for (Animals a : aList)
                a.say();
        }
    
        }
    
    }
    

    相信我,如果你能分析一下这里的抽象层次,那就太棒了。 如果你使用更高级别的抽象,你甚至可以去掉这里的类型;你可以阅读《抽象工厂设计》。通过这种方式,您公开了最少的类特性(例如,在这里,您通过将它们直接用于主类中的new来公开Dog和Cat类)。如果你满意,请投赞成票。