[英]Case when method in mixin depends on a method of the class that mixin-ed to
當 mixin 中的方法依賴於 class 的 mixin 方法時,我想問一下設計模式。 下面的例子是 python,但我相信其他語言也會出現這個問題。
例如,假設我有以下兩個混入,我想注入一些 class。在下面的代碼中,我想注入f
但f
要求 class 混入來實現g
,因為g
將是用於f
from abc import ABC, abstractmethod
class MixinBase(ABC):
@abstractmethod
def f(self, a: int) -> int: ...
# the main function that we want to mix-in
@abstractmethod
def g(self, a: int) -> int: ...
# a method that we know that is used in f()
class Mixin1(MixinBase):
def f(self, a: int) -> int: return self.g(a) ** 2
class Mixin2(MixinBase):
def f(self, a: int) -> int: return self.g(a) + 2
現在,我的問題是,注入此類 mixin 的更好做法是什么?
我可以想出以下兩種混合方式。 第一種情況是隱式的:
class ImplicitExample:
def g(self, a: int): return a
## and other methods ...
class ImplicitExampleWithMixin1(ImplicitExample, Mixin1): ...
class ImplicitExampleWithMixin2(ImplicitExample, Mixin2): ...
這種混合是隱含的,因為 ImplicitExample 的實現者ImplicitExample
地知道混入對ImplicitExample
的依賴性。
另一種混合方式是顯式繼承MixinBase
以保證g
被實現。
class ExplicitExample(MixinBase):
def g(self, a: int): return a
# and other methods ...
class ExplicitExampleWithMixin1(ExplicitExample, Mixin1): ...
class ExplicitExampleWithMixin2(ExplicitExample, Mixin2): ...
我認為以上兩個例子各有利弊。 第一個顯式是更簡單的依賴圖,但實現者必須知道隱式依賴。 另一方面,對於第二個顯式示例,實現者的精神壓力較小,但這會導致菱形依賴圖。 如果 MixIn 很少,那還好,但如果很多,精神壓力可能會很大。
就個人而言,我可能只是在Mixin
的文檔字符串中記錄依賴關系,並將Mixin.g()
定義為文檔字符串加上一行: raise NotImplementedError()
。 我也可能會跳過在Mixin
class 的所有外部文檔中定義g()
。細節可能取決於個人偏好以及您希望Mixin
的使用方式/由誰使用; 一個為內部使用定義Mixin
的小組項目將對可移植性和文檔有不同的要求,而不是公開訪問的開源庫的一部分。 這些要求應該會影響您在 class 設計中的想法。
如果你有更復雜的依賴關系——多個東西以不同的方式調用g()
,幾個嵌套的函數/mixins 必須一起工作,或者其他復雜情況,那么我建議多考慮一下依賴關系圖。 但是正如你在這里介紹的那樣? 哪個都好
我不會強調細節的原因:
g()
提供一個不太可能被意外復制的記錄良好的名稱,它本身就不是問題……而且您可能應該這樣做。MixinUser.g()
並練習Mixin.f()
。 這演示了正確的用法(因此它是文檔)並確保如果子類化Mixin
的人遵循您的意圖, Mixin.f()
將按預期工作。簡而言之,您有幾個選擇,但只要您記錄依賴關系並為其編寫一些測試,您作為問題的一部分提出的大多數問題在實踐中就不太可能成為問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.