面向对象三大特征

面向对象三大特性

一、封装

封装是面向对象的三大特征之一。它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类提供的方法来实现对内部信息的操作和访问。

我认为封装是面向对象编程语言对客观世界的模拟,在客观世界里,对象的状态信息都被隐藏在对象内部,外界无法直接操作和修改。对一个类或对象实现良的封装,有以下好处:

  1. 隐藏实现细节:外部代码不需要了解对象的内部实现,只需调用提供的接口即可。

  2. 提高安全性:可以限制对对象内部数据的直接访问,从而避免不合理的修改。

  3. 简化接口:将复杂的实现隐藏起来,提供简单易用的接口,使得使用者只需要关心如何使用而不需要了解内部的复杂实现。

  4. 提高代码可维护性:修改内部实现不会影响到外部代码,只需要确保接口的行为保持一致即可。

  5. 增强代码的可重用性:封装使得代码模块可以在不同的项目中复用,提高了开发效率。

从设计角度讲,封装应该遵循:

  1. 分而治之
  • 将一个大的需求分解为多个类,每个类处理一个独立的功能。
  • 拆分的好处:便于分工,便于复用,可扩展性强。
  1. 变则疏之
  • 变化的地方独立封装,避免影响其他类。
  1. 高内聚
  • 类中各个方法都在完成一项任务(单一职责的类)。
  1. 低耦合
  • 类与类的关联性与依赖性要低(每个类独立),让一个类的改变,尽少影响其他类。

二、继承

继承可以让子类具有父类的特征,提高了代码的复用性。
从设计上是一种增量净化,原有父类设计不变的情况下,可以增加新的功能,或者改进已有的算法。
继承是面向对象程序设计的重要特征,也是实现“代码复用”的重要手段。
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
例如:

猫可以:喵喵叫、吃、喝、拉、撒
狗可以:汪汪叫、吃、喝、拉、撒
吃、喝、拉、撒是猫和狗都具有的功能,如果分开写猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:
  动物:吃、喝、拉、撒
   猫:喵喵叫(猫继承动物的功能)
   狗:汪汪叫(狗继承动物的功能)

PS:在Python3中所有类均继承于object类,故没有经典类和新式类的说法,在Python2中继承于object类的称为新式类,没有继承于object类称为经典类。
继承的实际案例:

"""继承的实际案例"""


class People():
    school = 'SH'
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class Student(People):
    def __init__(self, name, age, gender, course=None):
        if course is None:
            course = []
        """子类里面一定再次调用父类的__init__方法"""
        People.__init__(self, name, age, gender) # 指名道姓的调用方法
        self.course = course

    def choose_course(self):
        print('%s 选课成功, %s' % (self.name, self.course))


stu = Student('ly', 20, 'male')
print(stu.school)  # SH 属性的查找
print(stu.name)
print(stu.age)
print(stu.gender)


class Teacher(People):
    def __init__(self, name, age, gender, level):
        People.__init__(self, name, age, gender)
        self.level = level

    def score(self, stu_name):
        print('%s 得了%s分' % (stu_name, 10))

tea = Teacher('kevin', 19, 'female')
print(tea.name)
print(tea.age)
print(tea.gender)
单继承下的属性查找

单继承下的属性查找:先从对象自己名称空间中查找,然后去产生这个对象的类中查找,最后去继承的父类中查找。

class A():
	def f2(self):
		pass

class B(A):
	def __f1(self):  # _Foo_f1
		print("from Foo.f1")

class Bar(Foo):
	def __f1(self):  # _Bar_f1
		print("from Bar.f1")

obj = Bar()
obj.f2()
多继承下的属性查找

多继承下分菱形查找和非菱形查找

菱形查找分 经典类 和 新式类
经典类:按照深度优先的查找顺序
新式类:按照广度优先查找
以下为经典类深度优先,了解即可。

class G: # 在python2中,未继承object的类及其子类,都是经典类
    def test(self):
        print('from G')

class E(G):
    def test(self):
        print('from E')

class F(G):
    def test(self):
        print('from F')

class B(E):
    def test(self):
        print('from B')

class C(F):
    def test(self):
        print('from C')

class D(G):
    def test(self):
        print('from D')

class A(B,C,D):
    # def test(self):
    #     print('from A')
    pass

obj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->G->C->F->D->object
mro和C3算法

如果类中存在继承关系,在可以通过mro()获取当前类的继承关系,(找成员的顺序)。而mro算法是通过C3算法实现的。
示例:
在这里插入图片描述
如上图:A 继承于B和C,则mro如下:

mro(A) = [A] + [B, C]
mro(A) = [A, B, C]

C3算法如下:

mro(A) = [A] + merge(mro(B), mro(C), [B,C])
mro(A) = [A] + merge([B, object], [C, object], [B,C])
mro(A) = [A] + [B] + merge([object], [C, object], [C])
mro(A) = [A] + [B,C] + merge([object, object])
mro(A) = [A] + [B, C, object]
mro(A) = [A, B, C, object]
super的使用

super()代表父类,可通过super调用父类方法等:
示例:

class A:
    def test(self):
        super().test()


class B:
    def test(self):
        print('from B')


class C(A, B):
    pass

多态

多态是指同一个方法调用由于对象不同会产生不同的行为。父类的同一种动作或者行为,在不同的子类上有不同的实现。多态增加了程序的灵活性。增加程序的可扩展性。
来看一个没有多态的代码:

class ArmyDog(object):
	def bite_enemy(self):
		print("追击敌人")

class DrugDog(object):
	def track_drug(self):
		print("追查毒品")

class Person(object):
	def work_with_army(self,dog):
		dog.bite_enemy()

	def work_with_drug(self,dog):
		dog.track_drug()

p = Person()
p.work_with_army(ArmyDog())
p.work_with_drug(DrugDog())

不难看出,如果添加一个类,继承dog,代码的增加是很麻烦的。
下面看一个有多态的情形:

class Dog(object):
	def work(self):
		pass

class ArmyDog(Dog):
	def work(self):
		print("追击敌人")
	
class DrugDog(Dog):
	def work(self):
		print("追击毒品")

class Person(object):
	def work_with_dog(self, dog):
		dog.work()

p = Person()
p.work_with_dog(ArmyDog())
p.work_with_dog(DrugDog())

这样,类的添加就显得很方便。
PS:多态度要注意一下两个点
1. 多态是方法的多态,属性没有多态。
2. 多态以继承和重写父类方法为前提

可以通过abc模块限制子类必须对父类方法进行重写
示例:

import abc # abstract class 抽象类   具体的Specific

class Animal(metaclass=abc.ABCMeta): # 把animal类变成了抽象类
    """父类中得方法不是为了实现逻辑的,实现功能的,而是单纯的为了限制子类的行为"""
    @abc.abstractmethod # 把抽象类中得方法变成抽象方法, 它不实现具体的功能,就是单纯的为了限制子类中的方法
    def speak(self):
        pass
    @abc.abstractmethod
    def jiao(self):
        pass


"""抽象类和普通类有什么区别? 抽象类只能够被继承、不能够被实例化"""

# Animal() # Can't instantiate abstract class Animal with abstract methods speak

鸭子类型
"""Python崇尚的是鸭子类型"""

"""鸭子类型就是更多的关注的是对象的行为,而不是对象的类型"""

class People(Animal):
    def speak(self):pass
        # print('from People.speak')
    def jiao(self):
        pass

class Dog(Animal):
    def speak(self):
        pass


class Pig(Animal):
    def speak(self):
        pass

"""多态带来的特性:在不考虑对象类型的情况下,直接调用对象的方法或者属性"""
def animal(obj):
    return obj.speak()

animal(obj)
animal(obj1)
animal(obj2)

"""面试题:请举出Python中使用多态的例子:len"""

len('hello')
len([1,2,3,4])
len((1,2,3,4))


def len(obj):
    return obj.__len__
len('helloworld')
len([1,2,3,4])
len((1,2,3,4))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值