体の調子がまだ少し悪い。今日もとっとと寝よう。その前に檜山さんの疑問に答えておこう。次のコードが答えです。
#vim: flleencoding=utf8
class User(object):
def __init__(self, id=None, handle=None):
if id and handle or not id and not handle:
raise Exception('id と handle の一方を指定する必要があります')
self.__id = id
self.__handle = handle
def __get_id(self):
return self.__id
def __set_id(self, id):
if self.__handle and id:
raise Exception('既に handle が設定されています')
self.__id = id
id = property(__get_id, __set_id)
def __get_handle(self):
return self.__handle
def __set_handle(self, handle):
if self.__id and handle:
raise Exception('既に id が設定されています')
self.__handle = handle
handle = property(__get_handle, __set_handle)
a = User(id=1) # id だけを使う
b = User(handle="foo") # handle だけを使う
c = User(id=2, handle="bar") # これはダメ
d = User(id=3)
d.handle = "hoge" # ダメ
e = User(id=4)
e._User_handle = "hage" # 実は通ってしまうが、こんなことする奴はわかっててやってんだろ。
まあやってることはプロパティで値を監視して、普通の方法ならアクセス出来なくしているというだけ。上記の通り self._User_id などとしてサブクラスやクラス外部からアクセスできてしまうわけで、そういった可能性を全部つぶすのは理論的には不可能なのだけど。俺としては、サブクラスと外部から普通の方法で問題のある値がセットされなければ十分だと思う。
[ここにあったのは間違った奴だったので削除。下のコードの __init__ の頭二行が抜けて、 typpo があった。]
さらに追記: これでどうだ。
class User(object):
def __init__(self, id=None, handle=None):
object.__setattr__(self, '_User__id', None)
object.__setattr__(self, '_User__handle', None)
if id and handle or not id and not handle:
raise Exception('id と handle の一方を指定する必要があります')
self.__id = id
self.__handle = handle
def __setattr__(self, name, value):
if name == '_User__handle' and value and self.__id:
raise Exception('だから id と handle を同時にセットするな')
elif name == '_User__id' and value and self.__handle:
raise Exception('だから id と handle を同時にセットするな')
else:
object.__setattr__(self, name, value)
# ここからは省略
どうでもいいが、俺の胃袋に合った分量を出してくれる店はないものか。牛丼の並盛でもちょっと多いかなと感じるんだが。