I solve this problem:
Develop an application which operates with next types:
Person(fieldName, methodShowData())Student(fieldEducation)Worker(fieldWorkPlace)
Classes Student and Worker are derived from class Person.
Class Academy in it's container collects Students and Workers and shows Name, Education or WorkPlace for all persons in method ShowAll().
We can add new persons to Academy by calling method AddPerson().
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:
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:
def add(self,name):
super(Academy,self).__init__(name)
-
2Looks like homework, but I'll say showAll should not be a staticmethod.postelrich– postelrich2015年09月09日 21:21:18 +00:00Commented Sep 9, 2015 at 21:21
-
2And this is fall again! Another batch of students struggling to get their homework done on SO ;-)zmo– zmo2015年09月09日 21:26:53 +00:00Commented Sep 9, 2015 at 21:26
2 Answers 2
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, i.e. a class having a single instance.
Also theWholeList is a very bad name for a list. Because you know it is a list, as you're assigning it a list. The name shall describe its semantic, i.e. 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. And what if you decide to change Academy's implementation so theWholeList is renamed? Or switched into a dict()? This should be transparent to the "user" of the class 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:
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!
6 Comments
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. 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:
def ShowData(self):
print 'Name: ' + self.name + ', Education:' + self.edu