きくらげ観察日記

好きなことを、適当に。

Pythonでsealedクラス

とくに意味も用途もないけど何となく思いついたので作ってみました。

sealedクラスとはScalaの機能で、別モジュールからの継承をできなくさせる機能です。

# sealed.py

class SealedException(Exception):
    pass

class SealedMeta(type):
    def __init__(self, name, bases, methods):
        super().__init__(name, bases, methods)

        for parent in bases:
            try:
                if parent._SEALED_BASE_DEFINED_AT != self.__module__:
                    # sealedなクラスを継承した子
                    raise SealedException('do not inherit %s' % parent.__name__)
            except AttributeError:
                # _SEALED_BASE_DEFINED_AT が存在しない場合は無視
                pass
        # ここまで辿り着く場合は、別モジュールで継承されたくない親クラス
        self._SEALED_BASE_DEFINED_AT = self.__module__

class Parent(metaclass=SealedMeta):
    pass

class Child1(Parent): # 同じモジュール内なので継承できる
    pass

使用例。sealed.pyをロードしたインタプリタ側からは、sealed.Parentを継承できなくなっています。

>>> import sealed
>>> class Child2(sealed.Parent): #
...   pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/gobba/Program/gomicode/Python/sealed.py", line 14, in __init__
    raise SealedException('do not inherit %s' % parent.__name__)
sealed.SealedException: do not inherit Parent