面向对象OOP
- 类(Class)
- 对象(Object)
- 实例(Instance)
类: 是一个抽象的存在实例: 是真实存在的类
对象: 是类的实例
好比说 门 就是一个类, 我的 屋门 就是门的一个实例. 我的屋门是白颜色的, 而且打开和关闭时会发出声响.
不管是 颜色, 还是打开和关闭 都是类赋予的属性和行为. 至于白颜色和打开和关闭时发出的声响是这个实例的具体表现.
对象: 包括了 类的属性和行为, 还有实例所都有的具体表现形式(比如: 白颜色, 打开和关闭时发出声响)
在面向对象的程序设计中, 首先要抽离出实体, 以及这个实体所拥有的属性和行为(方法).
面向对象的三大特点: 封装, 继承, 多态
封装
class Animal(object):
def __init__(self, args):
super(Animal, self).__init__()
self.__name = args.get("name")
self.age = args.get("age")
def call(self):
print("Animal(name:{0}, age:{1}) Call....".format(self.__name, self.age));
def setAnimalInfo(self, *, name, age):
self.__name = name
self.age = age
def getAnimalInfo(self):
return {"name": self.__name, "age": self.age}
def __str__(self): # 重写父类方法
return "Animal(name:{0}, age:{1})".format(self.__name, self.age)
pig = Animal({})
pig.setAnimalInfo(name="tom", age=2)
pig.call()
pig.age = 3
print(pig.age)
print(pig._Animal__name) # 不建议这样访问
# print(pig.__name) # AttributeError: 'Animal' object has no attribute '__name'
pig.__name = "jack" # 这么写是错误的, 虽然Python没有限制
print(pig.__name) # 实际上就是给 pig 绑了一个新的属性
pig.call()
所谓封装, 就是将类的属性设为私有, 然后开放属性的get, set方法. 这样会提高程序的健壮性(比如set时, 验证实参是否合法)
因为构造方法(__init__(self
, args))中, 存在必选参数, 所以在初始化实例时 pig = Animal({})
实际上私有属性, 在实例化对象时, 就已经改了变量名, 所以才有的 AttributeError: 'Animal' object has no attribute '__name'
的错误信息
pig.__name = "jack"
就像当于给pig实例, 重新绑定了新的属性(这样写虽然语法没有错, 但不建议这样写. 就像某件事, 没有触犯法律, 但受到道德的谴责.)
继承
class Animal(object)
Animal 继承自 object,
class Dog(Animal):
def __init__(self, args):
super(Dog, self).__init__(args)
def call(self):
# print("Dog(name:{0}, age:{1}) wang....".format(super().__name, super.age));
print("Dog(name:{0}, age:{1}) wang....".format(super(Dog, self).getAnimalInfo().get("name"),
super(Dog, self).getAnimalInfo().get("age")));
def __str__(self): # 重写父类方法
# return "Dog(name:{0}, age:{1})".format(super().__name, super.age)
return "Dog(name:{0}, age:{1})".format(super(Dog, self).getAnimalInfo().get("name"),
super(Dog, self).getAnimalInfo().get("age"))
class Cat(Animal):
def __init__(self, args):
super(Cat, self).__init__(args)
def call(self):
# print("Cat(name:{0}, age:{1}) miao....".format(self.__name, self.age));
print("Cat(name:{0}, age:{1}) miao....".format(super(Cat, self).getAnimalInfo().get("name"),
super(Cat, self).getAnimalInfo().get("age")));
def __str__(self): # 重写父类方法
# return "Cat(name:{0}, age:{1})".format(self.__name, self.age)
return "Cat(name:{0}, age:{1})".format(super(Cat, self).getAnimalInfo().get("name"),
super(Cat, self).getAnimalInfo().get("age"))
dog = Dog({"name": "lucy", "age": 2})
cat = Cat({"name":"lola", "age":1})
dog.call()
cat.call()
print("pig is Animal", isinstance(pig, Animal))
print("dog is Dog", isinstance(dog, Dog))
print("cat is Cat", isinstance(cat, Cat))
print("dog is Animal", isinstance(dog, Animal))
print("cat is Animal", isinstance(cat, Animal))
在子类中, 获取父类的引用 super(Dog, self)
. 而在子类中要想拿到父类的属性, 只能通过父类中提供的开放接口, 来实现了.
多态
从上面的程序中可以看出, Animal重写了他的父类的__str__方法, Cat和Dog也重写了这个方法. 有继承和方法重写, 自然就有多态了.
def getAnimal(animal):
print(animal)
getAnimal(pig)
getAnimal(dog)
getAnimal(cat)
# Animal(name:tom, age:3)
# Dog(name:lucy, age:2)
# Cat(name:lola, age:1)
虽传入的都是 Animal类, 但执行的却有着不同的行为. 这就是多态(^_^)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。