java - Java 抽象:抽象类委托抽象与具体类使用通用抽象
问题描述
假设我正在实现一个像 Animal 这样的简单接口。从广义上讲,有两种方法可以做到这一点:
- 在抽象类中实现接口的方法,并为所需的任何实现特定逻辑创建抽象方法。
- 在具体类中实现接口方法,在访问受保护的抽象类中移动通用逻辑。
我想了解如果——
- 在设计方面,一种方式比另一种方式有任何客观的好处。
- 是否建议在单个项目中仅使用一种方式(代码可维护性/可读性)。
public interface Animal {
void makeSound();
}
public abstract class BaseAnimal implements Animal {
@Override
public void makeSound() {
//do something which is common for all implementaions
doSomeImplementaionSpecificStuff();
}
public abstract void doSomeImplementaionSpecificStuff();
}
public class Dog extends BaseAnimal implements Animal {
public void doSomeImplementationSpecificStuff(){
//do something specific to a dog
}
}
public abstract class BaseAnimal implements Animal {
public void doCommonStuff() {
//any common logic that can be shared between concrete implementation goes here
}
}
public class Dog extends BaseAnimal implements Animal {
@Override
public void makeSound() {
doCommonStuff();
//do something specific to a dog
}
}
解决方案
这两种方式并不总是可以互换的。
您的第一个示例为子类设置了一个约束,该约束需要实现作为该方法一部分的特定makeSound()
方法。
使用这种方式将子类的实现强耦合到父类之一。
此外,子类可能仍然是子类makeSound()
,因为它不是final
。
所以我只会在非常具体的场景中使用这种方式:
- 定义一个子类必须定义的工厂方法,因为父类依赖于它(抽象工厂)
- 定义通用算法并让子类定义该算法的某些特定部分(模板方法)。
在一般情况下,您想使用第二个示例的代码,但也可以这样BaseAnimal
做Animal
:
public abstract class BaseAnimal implements Animal {
public void doCommonStuff() {
//any common logic that can be shared between concrete implementation goes here
}
}
public class Dog extends BaseAnimal implements Animal {
@Override
public void makeSound() {
doCommonStuff();
//do something specific to a dog
}
}
请注意,在 Java 8 中,默认接口依赖于您定义仅定义通用方法的抽象类:
public interface Animal {
void makeSound();
default void doCommonStuff() {
//any common logic that can be shared between concrete implementation goes here
}
另请注意,doCommonStuff()
在抽象类的 API 中公开不一定很好。客户端应该可以调用它吗?如果这是一个实现细节,您可以将其提取到支持类 ( ) 中,并通过将 an 组合到子类中AnimalDelegate
来支持组合而不是继承。 AnimalDelegate
Animal
推荐阅读
- azure - 将错误从 Azure 数据工厂记录到 Application Insights(ADF 到 ApplicationInsights)
- mongodb - Elasticsearch 7.1:将 mongodb 聚合管道转换为弹性搜索查询
- delphi - 如何在 Delphi 中将“字符集”转换为“字节集”
- scheme - 作为标准,Scheme 是否有任何用于调用 let 的语法糖?
- python - 使用 Multiprocessing Poolmap 执行进程时,该进程未完成
- python - 在python中为极坐标图添加标签
- android - CameraX 多个后置摄像头
- c++ - OpenMP 返回错误结果
- go - 安装链码后尝试查询状态数据库时出现 Hyperledger 错误
- mysql - SQL查询构建,需要建议