面向对象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({})

clipboard.png

实际上私有属性, 在实例化对象时, 就已经改了变量名, 所以才有的 AttributeError: 'Animal' object has no attribute '__name' 的错误信息

clipboard.png

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类, 但执行的却有着不同的行为. 这就是多态(^_^)


Striveonger
12 声望0 粉丝

Bug 一样的人生, 不需要解释.