构造函数参数与抽象成员(Class 与抽象Class)
Constructor Parameters vs Abstract Members (Class vs Abstract Class)
我什么时候应该使用抽象 class 与常规 class?更具体地说,我试图了解何时应该优先使用构造函数参数而不是抽象成员。
例如:
sealed trait Client
abstract class BaseService {
def client: Client
}
class Service extends BaseService {
val client = ???
}
对
sealed trait Client
class BaseService(client: Client) {}
class Service extends BaseService(client = ???)
据我所知,两者都是有效的。
正如@Luis Miguel 所说,当您想声明一组需要由子classes and/or 共享实现的通用方法时,请使用抽象classes所有子 classes.
都将使用的一些有限功能
下面,我列出了一些我认为您应该将依赖项传递给构造函数而不是在 classes/base-classes 中定义它们的原因。
使用依赖注入
(恕我直言)最好为构造函数提供正常运行所需的依赖项 AKA dependency injection。
避免紧耦合
当您在 class 或构造函数中声明依赖项时,您 将 您的 Service
与依赖项的特定实现紧密耦合,这并不理想,是 considered an antipattern.
接口编程,而不是实现
注入依赖项为您提供了更大的灵活性,因为您没有耦合到特定的实现。 只要您的代码依赖于 interface/trait/abstract-class(从而避免紧耦合),这就是事实。
当您的 class 依赖于 interface/trait/abstract-class 时,您可能会非常强大,因为您可以传递模拟、空操作或客户端的不同策略。所以确保你 "Program to interfaces, not implementations".
我什么时候应该使用抽象 class 与常规 class?更具体地说,我试图了解何时应该优先使用构造函数参数而不是抽象成员。
例如:
sealed trait Client
abstract class BaseService {
def client: Client
}
class Service extends BaseService {
val client = ???
}
对
sealed trait Client
class BaseService(client: Client) {}
class Service extends BaseService(client = ???)
据我所知,两者都是有效的。
正如@Luis Miguel 所说,当您想声明一组需要由子classes and/or 共享实现的通用方法时,请使用抽象classes所有子 classes.
都将使用的一些有限功能下面,我列出了一些我认为您应该将依赖项传递给构造函数而不是在 classes/base-classes 中定义它们的原因。
使用依赖注入
(恕我直言)最好为构造函数提供正常运行所需的依赖项 AKA dependency injection。
避免紧耦合
当您在 class 或构造函数中声明依赖项时,您 将 您的 Service
与依赖项的特定实现紧密耦合,这并不理想,是 considered an antipattern.
接口编程,而不是实现
注入依赖项为您提供了更大的灵活性,因为您没有耦合到特定的实现。 只要您的代码依赖于 interface/trait/abstract-class(从而避免紧耦合),这就是事实。
当您的 class 依赖于 interface/trait/abstract-class 时,您可能会非常强大,因为您可以传递模拟、空操作或客户端的不同策略。所以确保你 "Program to interfaces, not implementations".