java - 如何向类型层次结构中的类添加缺失的方法以允许统一处理?

标签 java oop design-patterns

我正在使用 Java 8/Java 11。我有一个类型层次结构(基本上是 dtos 或 Java Beans),例如

public abstract class Animal {
  public abstract String getName();
  public abstract int getAge();
}

以及一些提供附加属性的实现:

public class Dog extends Animal {

  // implementation of abstract methods from base class animal

  // additional properties
  public String getSound() {
    return "woof";
  }
}

public class Dog extends Animal {

  // implementation of abstract methods from base class animal

  // additional properties
  public String getSound() {
    return "miaow";
  }
}

public class Fish extends Animal {
  // implementation of abstract methods from base class animal

  // no implementaion for "getSound()"
}

现在,我想以统一的方式处理 AnimalCollection,例如

animals.forEach(x -> {
  System.out.println(x.getName());  // works
  System.out.println(x.getSound();  // doesn't work, as Fish is missing the method
});

我想知道,假设它们应该返回一个默认值,例如 String 的“n/a”,那么实现“缺失”方法的好方法是什么。

一种明显的方法是将所有缺少的方法移至基类,并声明它们是抽象的或提供默认实现。 但我想让它们更加分开,即明确为“统一处理”添加了哪些属性。 另一种方法是引入一个辅助类,使用 instance of 来确定该方法是否丢失:

public class AnimalHelper {

  public static String getSoundOrDefault(Animal animal) {
    if (animal instanceof Dog) {
        return ((Dog)animal).getSound();
    }

    if (animal instanceof Cat) {
        return ((Cat)animal).getSound();
    }
    return "n/a";
  }
}

然后用Animal调用它:

System.out.println(AnimalHelper.getSoundOrDefault(animal));

这可行,但调用者现在必须直接调用 Animal 的哪些方法以及对哪些方法使用助手。

另一个解决方案,我想出了使用默认实现的 Java 8 功能添加一个接口(interface) AnimalAdapter:

public interface AnimalAdapter {

  default String getSoundOrDefault() {
    return "n/a";
  }
}

并将其添加到 Animal 类中:

public abstract class Animal implements AnimalAdapter {
...

这会导致在 DogCat 中添加 getSoundOrDefault() 方法,但不会在 Fish 中添加:

public class Dog extends Animal {
  ...
  @Override
  public String getSoundOrDefault() {
    return getSound();
  }
}

(同样在Cat中)。

对上述考虑因素或其他想法的任何评论将受到高度赞赏。

最佳答案

您上面提到的所有解决方案都非常好。但我利用多态性技术添加了更多一种解决方案,并且我认为它在代码方面更简单且更便宜。 简而言之,我将使用 Object.toString() 方法来显示所有需要的参数,因此首先您必须 @Override toString() 方法,如下所示:

  public class Dog extends Animal {

      // implementation of abstract methods from base class animal

      // additional properties
      public String getSound() {
        return "woof";
      }

       @Override
       public String toString() {
        return getName() + "\n" + getSound();
       }
  }

  public class Fish extends Animal {

      // implementation of abstract methods from base class animal

      // no implementaion for "getSound()"

      @Override
      public String toString() {
        return getName() + "\n" + "n/a";
      }
  }

  public class Main {

     public static void main(String[] args) {
       Collection<Animal> animals = new ArrayList<>(2);
       animals.add(new Dog());
       animals.add(new Fish());
       animals.forEach(System.out::println);
    }
 }

这是结果:

enter image description here

关于java - 如何向类型层次结构中的类添加缺失的方法以允许统一处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60900170/

相关文章:

java - 将 Java Cryptography Extension Unlimited Strength 添加到我的可执行文件中或自动安装

java - 在 Spring bean 中实现空对象设计模式

oop - 解耦一个被大量子类使用的类

java - 自动生成 Java 接口(interface)的不可变类和匹配的构建器类

java - 类层次结构爆炸

java - Swing 多线程。我的 GUI 卡住了

java - IntelliJ IDEA 无法自动导入

java - 存储库模式 - 复合对象的 Java 示例

c++ - 从派生类构造函数初始化 protected 数据成员

c++ - 单例实例声明为 GetInstance 方法的静态变量,它是线程安全的吗?