「もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルである」
という説明がよく使われますが、
一言で言うと、「継承してなくてもサブクラスとして見なすための仕組み」といった感じです。
以下、実際のコードで示します。
以下、実際のコードで説明します。
import abc
def main():
subhoge_instance = SubHoge()
print(isinstance(subhoge_instance, Hoge)) # => True
print(issubclass(SubHoge, Hoge)) # => True
huga_instance = Huga()
print(issubclass(Huga, Hoge)) # => False
print(isinstance(huga_instance, Hoge)) # => False
class Hoge(metaclass=abc.ABCMeta):
@classmethod
def __subclasshook__(Class, Subclass):
print("subclasshook is called")
attributes = []
for cls in Subclass.__mro__:
attributes.extend(cls.__dict__.keys())
methods = ("hoge", "huga")
if all(method in attributes for method in methods):
return True
return NotImplemented
class SubHoge:
def hoge():
pass
def huga():
pass
class Huga:
def piyo():
pass
if __name__ == "__main__":
main()
確かに、hogeとhugaメソッドを実装しているSubHogeクラスはHogeクラスの子クラスとみなし、
そうでないHugaクラスはHogeクラスの子クラスとみなされていないことがわかると思います。
Subclass.__mro__
Pythonの組み込み型です。
ざっくり言うと、そのクラス自身と親クラス(基底クラス)を配列として返します。
さっくり確認したい場合はprint(SubHoge.__mro__)
と打つとSubclassおよびSubclassの親クラスを確認できます。
cls.__dict__
こちらもPythonの組み込み型です。
ざっくり言うと、そのクラスの持つメソッドなどを返してくれます。
さっくり確認したい場合はprint(SubHoge.__dict__.keys())
と打つとSubclassの持つメソッドを確認できます。