I'd like to ask the design pattern when method in a mixin depends on a method of the class that mixin-ed to. The example below is in python, but the question will be also the case with other languages I believe.
For example, say I have the following two mixins, and I'd like to inject into some class. As in the code below I'd like to inject f
but f
requires that the class mixin-ed to implements g
because g
will be used in 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
Now, my question is, what is the better practice to inject such mixins?
example
I could come up with the following two ways to mixin. The case one is the implicit one:
class ImplicitExample:
def g(self, a: int): return a
## and other methods ...
class ImplicitExampleWithMixin1(ImplicitExample, Mixin1): ...
class ImplicitExampleWithMixin2(ImplicitExample, Mixin2): ...
This mixing is implicit in the sense that the implementer of ImplicitExample
implicitly know the dependency of the mixins on ImplicitExample
.
Another way of mixing is explicitly inherit the MixinBase
so that g
is guaranteed to be implemented.
class ExplicitExample(MixinBase):
def g(self, a: int): return a
# and other methods ...
class ExplicitExampleWithMixin1(ExplicitExample, Mixin1): ...
class ExplicitExampleWithMixin2(ExplicitExample, Mixin2): ...
I think the above two examples has pros-and-cons. The first explicit one is simpler dependency graph but the implementer must be aware the implicit dependency. On the other hand, for the second explicit example, mental stress of implementer is less intensive, but this causes diamond dependency graph. If MixIn is only few its ok, but if many mental stress could be intensive.