如果一个School
类依赖于一个EmailSender
类,您可能必须EmailSender
通过它的构造函数注入它,该类具有通用接口,例如IMessagable
orIMessageSender
甚至IEmailSender
,以便将来可以将其换成其他东西。
为此,您将在类中创建一个只读私有字段School
。
但是你是说School
HAS-A MessageSender
,但它肯定只是在它的一些方法中使用它?
如果一个School
类依赖于一个EmailSender
类,您可能必须EmailSender
通过它的构造函数注入它,该类具有通用接口,例如IMessagable
orIMessageSender
甚至IEmailSender
,以便将来可以将其换成其他东西。
为此,您将在类中创建一个只读私有字段School
。
但是你是说School
HAS-A MessageSender
,但它肯定只是在它的一些方法中使用它?
类声明的任何属性/成员都是类具有的东西。
Has-A 在这里与继承的 Is-A 区分开来。
uses-a 属性更多地与类凝聚力而不是组合相关。如果该类具有-A 属性但它不使用它,或者在一小部分函数中使用它,则它的内聚性低。
HAS-A 和 IS-A 都是类的依赖项。这就是为什么我们努力将它们都作为抽象,将两者松散耦合。
没有您的类将无法编译的任何类/接口定义都是依赖项。即使它没有 HAS-A 关系并且它只是作为函数参数传递。
即使一个类只使用传入对象中的许多方法之一,整个对象仍被视为该类的依赖项。
当您更改对象的 API(方法签名)时,这一点变得很明显。通过将该对象交给一个类,您基本上保证了该对象的“契约”。如果更改该对象的 API,则可能会破坏依赖它的类。
这就是为什么我们经常使用接口将依赖项传递给类的原因。接口强制类及其依赖项之间的契约,并鼓励解耦,因为传入的对象必须只符合接口的方法。
命名法IS-A和HAS-A主要用于区分继承和组合。