Q1。如果我有一个非常通用的类,并且其名称可以更好地表示在更特定的继承类中,那么我该如何从父类访问相同的方法(如果该属性具有改了名字?例如(不是我的真实情况,但它显示了我的意思)。
class Entity(object):
def __init__(self):
self.members= {}
... # Methods that use self.members
class School(Entity):
def __init__(self):
super(Entity,self).__init__(self)
class Company(Entity):
def __init__(self):
super(Entity,self).__init__(self)
对于class School
和class Company
,我希望能够使用更具体的属性,例如self.students
和self.employees
,但仍然可以使用在self.members
中为class Entity
定义的方法。
第二季度。这是不好的做法吗?解决此问题的最佳方法是什么?在我的真实情况下,我用于self.members
的单词太笼统了。
答案 0 :(得分:0)
重命名子类中的属性通常是不好的做法。
原因是inheritance is about substitutability。 School
成为Entity
的意思是,您可以在任何期望使用School
的代码中使用Entity
,它可以正常工作。 / p>
例如,使用Entity
的典型代码可能会执行以下操作:
for member in entity.members:
如果您声称自己是Entity
(甚至通过了isinstance(myschool, Entity)
),但是没有members
或空白members
,因为其实际成员存储在其他属性中,所以该代码已损坏。
更一般地说,如果您更改基类和受约束的类之间的接口(一组公共方法和属性),则派生类不是子类型,这意味着它通常不应在第一个中使用继承。情况。 1
如果将students
设为members
的别名,那么可以使用 名称访问相同的属性,那么您 do 有一个子类型:School
的{{1}}为students
,因此可以合理地将其与期望members
的代码一起使用:>
Entity
这与myschool.students.append(Person(cap'))
# ...
for member in myschool.members:
# now cap is going to show up here
中定义的方法同样有效:
Entity
您可以使用@property
来做到这一点。
def slap_everyone(self):
for member in self.members:
# this will include cap
member.slap()
myschool.slap_everyone()
因此,这不是完全无效的。
但这可能会引起误解。
对您的代码读者来说,将class Student(Entity):
# ...
@property
def students(self):
return members
@students.setter
def students(self, val):
self.members = val
@students.deleter
def students(self):
del self.members
添加到cap
会不会将他添加到myschool.students
中,这是显而易见的吗?如果是这样,那可能没问题。如果不是,或者不确定,那么您可能不应该这样做。
要考虑的另一件事是,myschool.members
可能有多种成员:学生,老师,管理人员,在旧校园里闲逛的辍学学生,因为他们不知道在其他地方可以找到毒贩,……如果那是设计的一部分,那么您真正想要的是让成员成为一个属性,并且可能是一个只读属性, 2 ,每个子类都可以定义什么对该子类有意义的方式算作“成员”。
School
这将打印出来:
class Entity(object):
@property
def members(self):
return []
def rollcall(self):
return ', '.join(self.members)
class School(Entity):
def __init__(self):
super(School, self).__init__()
self.students, self.teachers = [], []
@property
def members(self):
return self.students + self.teachers
school = School()
school.teachers.append('cap')
school.students.extend(['marvel', 'america, planet'])
print(school.rollcall())
cap, marvel, america, planet
作为school
和School
工作,一切都很好。
1。我通常说 是因为(不管OO教义怎么说),除了子类型化之外,还有其他原因可以进行子类化。但这仍然是主要原因。在这种情况下,似乎没有其他任何原因可以进行子类化-您不是在尝试共享存储详细信息,不提供覆盖的钩子或类似的东西。
2。实际上,您可能甚至想要拖动Entity
模块并将其作为抽象属性……但是在这里我不会显示。