【问题标题】:Python understanding OOP, inheritancePython理解OOP、继承
【发布时间】:2015-09-09 21:09:39
【问题描述】:

我解决了这个问题:

开发一个使用下一个类型操作的应用程序:

  1. Person(字段Name,方法ShowData()
  2. Student(字段Education
  3. Worker(字段WorkPlace

StudentWorker 派生自类Person

Academy 在它的容器中收集StudentsWorkers 并为方法ShowAll() 中的所有人显示NameEducationWorkPlace

我们可以通过调用AddPerson()方法来添加新的人到Academy

哪个层次的类是最好的 解决这个问题?

代码应包括继承和使用集合。

这是我的解决方案,但我不知道如何实现方法AddPerson

class Academy(object):
    theWholeList = []
    @staticmethod
    def showAll():
        for obj in Academy.theWholeList:
            if isinstance(obj,Student):
                print obj.name+' - '+obj.edu
            elif isinstance(obj,Worker):
                print obj.name+' - '+obj.wplace

class Person(Academy):
    def __init__(self,name):
        self.name = name
        super(Person, self).theWholeList.append(self)

    def showData(self):
        return vars(self)

class Student(Person):

    def __init__(self, name, edu):
        super(Student, self).__init__(name)
        self.edu = edu

class Worker(Person):

    def __init__(self, name, wplace):
        super(Worker, self).__init__(name)
        self.wplace = wplace

也许Academy 必须继承Person 和方法AddPerson 会是这样的:

def add(self,name):
    super(Academy,self).__init__(name)

【问题讨论】:

  • 看起来像作业,但我会说 showAll 不应该是静态方法。
  • 又是秋天!另一批在 SO 上努力完成作业的学生 ;-)

标签: python python-2.7 oop inheritance


【解决方案1】:

第一件事:

class Academy(object):
    theWholeList = []
    @staticmethod
    def showAll():
        for obj in Academy.theWholeList:
            if isinstance(obj,Student):
                print obj.name+' - '+obj.edu
            elif isinstance(obj,Worker):
                print obj.name+' - '+obj.wplace

您不需要将 Academy 的方法 showAll() 设为静态方法,因为在您的设计中,学院是合法的单例,即具有单个实例的类。

另外,theWholeList 是一个非常糟糕的列表名称。因为您知道它是一个列表,因为您正在为其分配一个列表。名称应该描述它的语义,即它包含的东西的种类,它的用途。

你应该改写如下:

class Academy:
    def __init__(self):
        self.person_list = []

    def show_all(self):
        for item in self.person_list:
            item.show_data()

你会实例化一次:

学院 = 学院()

然后是:

class Person(Academy):
    def __init__(self,name):
        self.name = name
        super(Person, self).theWholeList.append(self)

是糟糕的设计:在面向对象编程中,您应该考虑封装数据。在这里,您假设Person 知道Academy 的内部结构。如果您决定更改Academy 的实现以重命名theWholeList 怎么办?还是改成dict()?这对Academy 类的“用户”应该是透明的。更好的设计应该是:

class Academy:
    ... # cf earlier

    def add_person(self, person):
        self.person_list.append(person)

class Person(Academy):
    def __init__(self,name):
        self.name = name

    def show_data(self):
        print("My name is: {}".format(name))

所以你可以这样使用它:

person_a = Person("John Doe")
person_b = Person("Jim Smith")
academy.add_person(person_a)
academy.add_person(person_b)

最后你想知道:

也许 Academy 必须继承 Person

大多数时候,子类化是对错误问题的错误回答。当您想要扩展专门化一个类的行为时,您需要子类化。一个经典的例子是:

class Animal:
    def noise(self):
        raise NotImplementedError # virtual method

class Duck(Animal):
    def noise(self):
        print("quack")

class Cat(Animal):
    def noise(self):
        print("meaw")

因此,在您的情况下,您有一个实现 show_data 的班级人员,您想要为工人和学生扩展行为:

class Worker(Person): # a worker _is_ a person!
    def __init__(self, name, unit):
        # left as an exercise to the OP

    def show_data(self):
        # left as an exercise to the OP

class Student(Person):
    def __init__(self, name, promo):
        # left as an exercise to the OP

    def show_data(self):
        # left as an exercise to the OP

我不会在这里详细介绍,因为我想您有一位老师,您可以询问更多关于我制作的 cmets 的信息。但至少你尝试过,犯了一些错误(而且错误是好的!)。但我并没有给你一个完整的答案,我在这里的唯一目标是让你有正确的心态,让你的代码设计得更好!

我希望这会有所帮助!

【讨论】:

  • 顺便说一句,将 Worker 和 Student 作为 Person 的子类也是不好的设计;这些是角色,而不是子类型。事实上,您可以轻松地同时兼顾两者。
  • @peter 我非常同意你的观点,但是我们可能需要告诉 OP 的老师他的练习很愚蠢 :-) 并不是所有的老师都以一种好的方式接受这样的批评(是的,我上大学的时候经常批评老师的习题)
  • 能够批评是一种技能。对老师说“这是愚蠢的设计”也是愚蠢的,但问“为什么你认为应该这样做?”或“可以改为这种方式建模吗?”极大地改变了对话。
  • 另外我其实是学生和工人,所以你甚至不能模仿我。 :(
  • 然后您可以进行菱形继承:-D(或如何在 Python 中导入 C++ OOP 疯狂:-p)
【解决方案2】:

您希望能够添加人员:

>>> academy = Academy()
>>> academy.add(Person('Pete'))
>>> academy.showAll()
Name: Pete

>>> academy.add(Student('Taras', 'Higher'))
>>> academy.showAll()
Name: Pete
Name: Taras, Education: Higher

>>> academy.add(Worker('riotburn', 'StackOverflow')
>>> academy.showAll()
Name: Pete
Name: Taras, Education: Higher
Name: riotburn, Workplace: StackOverflow

showAll 需要遍历所有调用ShowData 的人。这将针对每种类型以不同的方式实现。

class Academy(object):
    def __init__(self):
        self.people = []

    def add(self, person):
        self.people.append(person)

    def showAll(self):
        for person in self.people:
            person.ShowData()

例如,Worker 会将ShowData 实现为:

def ShowData(self):
    print 'Name: ' + self.name + ', Education:' + self.edu

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    相关资源
    最近更新 更多