包括的な概念の異なる実装または特殊化であるクラスのファミリーを作成したいとしましょう。一部の派生プロパティにもっともらしいデフォルト実装があると仮定しましょう。これを基本クラスに入れたい
class Math_Set_Base:
@property
def size(self):
return len(self.elements)
したがって、サブクラスは自動的にこのかなりばかげた例の要素を数えることができます
class Concrete_Math_Set(Math_Set_Base):
def __init__(self,*elements):
self.elements = elements
Concrete_Math_Set(1,2,3).size
# 3
しかし、サブクラスがこのデフォルトを使用したくない場合はどうなりますか?これは動作しません:
import math
class Square_Integers_Below(Math_Set_Base):
def __init__(self,cap):
self.size = int(math.sqrt(cap))
Square_Integers_Below(7)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "<stdin>", line 3, in __init__
# AttributeError: can't set attribute
プロパティをプロパティでオーバーライドする方法はあると思いますが、それは避けたいです。基本クラスの目的は、ユーザーの生活をできるだけ簡単にすることであり、(サブクラスの狭い観点から)複雑で余分なアクセスメソッドを課すことによって膨張を追加することではありません。
できますか?そうでない場合、次善の策は何ですか?
基本クラスのプロパティを、派生クラス内の派生クラスの別のプロパティに設定し、新しい値で基本クラスのプロパティを使用することは可能だと思います。
最初のコードでは、基本クラスの名前size
と派生クラスの属性self.size
の間に一種の矛盾があります。これは、派生クラスの名前self.size
をself.length
に置き換えると表示されます。これは出力します:
3
<__main__.Square_Integers_Below object at 0x000001BCD56B6080>
次に、プログラムのすべてのオカレンスでメソッドsize
をlength
に置き換えると、同じ例外が発生します。
Traceback (most recent call last):
File "C:/Users/Maria/Downloads/so_1.2.py", line 24, in <module>
Square_Integers_Below(7)
File "C:/Users/Maria/Downloads/so_1.2.py", line 21, in __init__
self.length = int(math.sqrt(cap))
AttributeError: can't set attribute
固定コード、またはとにかく機能するバージョンは、基本クラスからメソッドsize
を設定するクラスSquare_Integers_Below
を除いて、コードをまったく同じに保つことです。別の値に。
class Square_Integers_Below(Math_Set_Base):
def __init__(self,cap):
#Math_Set_Base.__init__(self)
self.length = int(math.sqrt(cap))
Math_Set_Base.size = self.length
def __repr__(self):
return str(self.size)
そして、すべてのプログラムを実行すると、出力は次のようになります。
3
2
これが何らかの形で役立つことを願っています。
また、次のことができます
class Math_Set_Base:
_size = None
def _size_call(self):
return len(self.elements)
@property
def size(self):
return self._size if self._size is not None else self._size_call()
class Concrete_Math_Set(Math_Set_Base):
def __init__(self, *elements):
self.elements = elements
class Square_Integers_Below(Math_Set_Base):
def __init__(self, cap):
self._size = int(math.sqrt(cap))