沒有辦法直接宣佈在Python向前引用,但有幾個解決方法,其中的一些是合理的:
1)添加它們被定義後,手動的子類。
- Pros: easy to do; Base.subs is updated in one place
- Cons: easy to forget (plus you don't want to do it this way)
實施例:
class Base(object):
pass
class Sub1(Base):
pass
class Sub2(Base):
pass
class Sub3(Base):
pass
Base.subs = [sub3, sub1]
2)創建Base.subs
與str
值,並使用class decorator
來代替實際的亞類(這可以是在基類方法或函數 - I顯示功能版本,但我可能會使用方法版本)。
- Pros: easy to do
- Cons: somewhat easy to forget;
實施例:
def register_with_Base(cls):
name = cls.__name__
index = Base.subs.index(name)
Base.subs[index] = cls
return cls
class Base(object):
subs = ['Sub3', 'Sub1']
@register_with_Base
class Sub1(Base):
pass
class Sub2(Base):
pass
@register_with_Base
class Sub3(Base):
pass
)創建Base.subs
與str
值,並且有一個使用Base.subs
做替代的方法。
- Pros: no extra work in decorators, no forgetting to update `subs` later
- Cons: small amount of extra work when accessing `subs`
例子:
class Base(object):
subs = ['Sub3', 'Sub1']
def select_sub(self, criteria):
for sub in self.subs:
sub = globals()[sub]
if #sub matches criteria#:
break
else:
# use a default, raise an exception, whatever
# use sub, which is the class defined below
class Sub1(Base):
pass
class Sub2(Base):
pass
class Sub3(Base):
pass
我會用選項我自己,因爲它使功能性和數據在同一個地方。你唯一需要做的就是保持subs
爲最新版本(當然寫下適當的子類)。
這是一個糟糕的設計。你正在將一個工廠(它知道子類)與超類(不需要知道子類)混爲一談。爲什麼要這樣做?爲什麼不簡單地分離事物並使事情更簡單? – 2010-11-12 11:03:38
@ S.Lott:如果它本身並不需要知道它的子類本身。它只需要在列表中有一堆類,其中一些可能是它的子類。 – pafcu 2010-11-12 11:44:04
@pafcu:「其中一些可能是它的子類」。這仍然是一個壞主意 - 超類不應該知道它的子類。這樣做違反了面向對象設計的原則。如果不更改超類,則不能再簡單地創建新的子類。你必須從超類中分離出「類的列表」。擁有「班級列表」的唯一原因是創建工廠。工廠是一件好事;但它不是超類的特徵。 – 2010-11-12 13:13:58