简体   繁体   English

Python理解OOP,继承

[英]Python understanding OOP, inheritance

I solve this problem: 我解决了这个问题:

Develop an application which operates with next types: 开发一个适用于以下类型的应用程序:

  1. Person (field Name , method ShowData() ) Person (字段Name ,方法ShowData()
  2. Student (field Education ) Student (实地Education
  3. Worker (field WorkPlace ) Worker (场WorkPlace

Classes Student and Worker are derived from class Person . StudentWorker派生自Person类。

Class Academy in it's container collects Students and Workers and shows Name , Education or WorkPlace for all persons in method ShowAll() . Academy在它的容器收集StudentsWorkers ,并显示NameEducationWorkPlace中的方法所有人ShowAll()

We can add new persons to Academy by calling method AddPerson() . 我们可以通过调用方法AddPerson()将新人添加到Academy

Which hierarchy of classes is the best for solving this problem? 哪个类的层次结构最适合解决这个问题?

Code should include inheritance and use collections. 代码应包括继承和使用集合。

This is my solution, but i don't know how to realize method AddPerson : 这是我的解决方案,但我不知道如何实现方法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

Maybe Academy must inherit Person and method AddPerson will be like that: 也许Academy必须继承Person和方法AddPerson将是这样的:

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

first thing: 第一件事:

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

you do not need to have Academy 's method showAll() be a static method, as on your design the Academy is legitimate to be a singleton, ie a class having a single instance. 你不需要Academy的方法showAll()是一个静态的方法,因为在你的设计中,学院是合法的单身,即一个具有单个实例的类。

Also theWholeList is a very bad name for a list. 此外, theWholeList是列表的一个非常糟糕的名称。 Because you know it is a list, as you're assigning it a list. 因为你知道它是一个列表,因为你要为它分配一个列表。 The name shall describe its semantic, ie the kind of things it contains, what it is used for. 名称应描述其语义,即它包含的东西的种类,它的用途。

You should rewrite it as follows: 你应该按如下方式重写它:

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

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

And you would instanciate it once: 而且你会一次实现它:

academy = Academy() 学院=学院()

Then the following: 然后是以下内容:

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

is bad design: in object oriented programming you should think about encapsulating data. 糟糕的设计:在面向对象的编程中,你应该考虑封装数据。 Here you're making the assumption that Person knows the internals of Academy . 在这里,你正在做的假设Person知道的内部Academy And what if you decide to change Academy 's implementation so theWholeList is renamed? 如果您决定更改Academy的实现以便重命名theWholeList ,该怎么办? Or switched into a dict() ? 或者切换成dict() This should be transparent to the "user" of the class Academy . 这应该对班级Academy的“用户”透明。 A better design should be: 更好的设计应该是:

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))

So you can use it as follows: 所以你可以按如下方式使用它:

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

And finally you're wondering: 最后你想知道:

Maybe Academy must inherit Person 也许学院必须继承人

Most of the time, subclassing is the wrong answer of a wrong question. 大多数时候,子类化是错误问题的错误答案。 You need to subclass when you want to extend or specialize behaviour of a class. 当您想要扩展专门化类的行为时,您需要子类。 A classical example would be: 一个经典的例子是:

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")

So in your case, you have a class person that implements show_data, and what you want is to extend the behaviour, for worker and student: 所以在你的情况下,你有一个实现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

I won't get into much more details here, as I suppose you have a teacher you can ask more about the comments I made. 我不会在这里得到更多细节,因为我想你有一位老师,你可以更多地询问我所做的评论。 But at least you tried, made some mistakes (AND MISTAKES ARE GOOD!). 但至少你试过,犯了一些错误(并且错误很好!)。 But I'm not giving you a full answer, my only goal here is to set you up in the right mind set to make your code a better design! 但是我没有给你一个完整的答案,我唯一的目标是让你在正确的思维定下让你的代码变得更好!

I hope this helps! 我希望这有帮助!

You want to be able to add people: 您希望能够添加人员:

>>> 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 needs to iterate over all people calling ShowData on them. showAll需要迭代调用ShowData所有人。 This will be implemented differently for each type. 对于每种类型,这将以不同方式实现。

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()

Where for example, Worker will implement ShowData as: 例如, Worker将实现ShowData

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM