Python小白学习笔记七 面向对象(三大特征与六大原则的理解)

三大特征与六大原则的理解

三大特征:封装,继承,多态

封装

数据角度讲

1.定义:将一些基本数据类型复合成一个自定义类型。

2.优势:将数据与对数据的操作相关联。

			 代码可读性更高(类是对象的模板)。
行为角度讲

1.定义:向类外提供必要的功能,隐藏实现的细节。

2.优势:简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。

3.私有成员:

	(1)作用:无需向类外提供的成员,可以通过私有化进行屏蔽。
	(2)做法:命名使用双下划线开头。
	(3)本质:障眼法,实际也可以访问。

私有成员的名称被修改为:_类名__成员名,可以通过_dict_属性或dir函数查看。

4.属性@property:
将方法的使用方式像操作变量一样方便,从而保护实例变量。

(1)定义:
@property

def 属性名(self):

				return self.__属性名

@属性名.setter

def 属性名(self, value):

				self.__属性名= value

(2)调用:

				对象.属性名 = 数据
				变量 = 对象.属性名

(3)说明:
通常两个公开的属性,保护一个私有的变量。

@property 负责读取,@属性名.setter 负责写入

只写:属性名= property(None, 写入方法名)

设计角度讲

1.定义:
(1) 分而治之:将一个大的需求分解为许多类,每个类处理一个独立的功能。

(2) 变则疏之:变化的地方独立封装,避免影响其他类。

(3) 高 内 聚:类中各个方法都在完成一项任务(单一职责的类)。

(4) 低 耦 合 :类与类的关联性与依赖度要低(每个类独立),让一个类的改变,尽少影响其他类。

2.优势:
便于分工,便于复用,可扩展性强。

继承

语法角度讲

继承方法

1.代码:

class 父类:
	def 父类方法(self):
	    方法体
class 子类(父类):
	def 子类方法(self):
		方法体

儿子 = 子类()

儿子.子类方法()

儿子.父类方法()

2.说明:
子类直接拥有父类的方法.

内置函数

		isinstance(对象, 类型) 

返回指定对象是否是某个类的对象。

		issubclass(类型,类型)

返回指定类型是否属于某个类型。

继承数据

1.代码

class 子类(父类):
	def __init__(self,参数列表):
		super().__init__(参数列表)
		self.自身实例变量 = 参数

2.说明
子类如果没有构造函数,将自动执行父类的,但如果有构造函数将覆盖父类的。此时必须通过super()函数调用父类的构造函数,以确保父类实例变量被正常创建。

定义:重用现有类的功能,并在此基础上进行扩展。

说明:子类直接具有父类的成员(共性),还可以扩展新功能。

优点:一种代码复用的方式。

缺点:耦合度高:父类的变化,直接影响子类。

设计角度讲

定义:将相关类的共性进行抽象,统一概念,隔离变化。

适用性

	多个类在概念上是一致的,且需要进行统一的处理。

相关概念

父类(基类、超类)、子类(派生类)。

父类相对于子类更抽象,范围更宽泛;子类相对于父类更具体,范围更狭小。

单继承:父类只有一个(例如 Java,C#)。

多继承:父类有多个(例如C++,Python)。

Object类:任何类都直接或间接继承自 object 类。

多继承

一个子类继承两个或两个以上的基类,父类中的属性和方法同时被子类继承下来。

同名方法的解析顺序(MRO, Method Resolution Order):

类自身 --> 父类继承列表(由左至右)–> 再上层父类

   A

  / \

 /   \

B     C

 \   /

  \ /

   D 

例如:

"""
    多继承
        如果父级具有同名方法,会在按照mro顺序调用.
        如果希望调用某个方法,通过类名.方法名(对象)
        继承不要作为代码的复用方式
        继承就是在隔离变化(多继承在隔离多种变化)
        继承:隔离变化
        组合:连接变化
"""
class A:
    def func01(self):
        print("A")

class B(A):
    def func01(self):
        print("B")

class C(A):
    def func01(self):
        print("C")

class D(C, B):
    def func01(self):
        print("D")
        # super().func01()
        A.func01(self)
d = D()
d.func01()
print(D.mro())

多态

设计角度讲

定义:父类的同一种动作或者行为,在不同的子类上有不同的实现。

作用

	1.在继承的基础上,体现类型的个性化(一个行为有不同的实现)。
	2.增强程序扩展性,体现开闭原则。
语法角度讲

重写

子类实现了父类中相同的方法(方法名、参数)。

在调用该方法时,实际执行的是子类的方法。

六大原则:开闭原则,单一原则,依赖倒置原则,组合复用原则,里氏替换原则,迪米特法则

开闭原则(终极目标)
			对扩展开放,对修改关闭。
			增加新功能,不改变原有代码。

开闭原则是代码编写的的终极目标,而面向对象的其他五个原则全部都是为开闭原则服务的,以开闭原则为基本目标,通过不同方法来降低耦合度。

“开”指的是允许一个类甚至往大了说允许一个系统随时可以对自己的功能进行拓展。

“闭”指的是不允许在扩展和修改功能的时候触及到已经写好的底层程序,所有这就要求在程序设计之初,尽可能考虑到一切需求,进行加粗样式抽象类,形成底层程序,之后不能再进行修改。

比如电脑,底层程序硬件构成都是不变的,通过程序编写(新增功能)来扩展自己的功能,但是本质上电脑的构成程序、硬件,并没有发生变化。

单一原则
		一个类有且只有一个改变它的原因。

对于单一原则,其核心思想为:一个类,最好只做一件事,只有一个可以引起它变化的因素,如果一个类封装太多变化,就可能导致牵一发而动全身,这样对系统来说会有风险。

一个类或者模块应该有且只有一个改变的原因。

	例如,搓衣板,既可以用来跪,也可以用来洗衣服。而在单一职责原理下,
搓衣板的两个功能就是引起这个类变化的两个原因,就应该写成两个类
依赖倒置原则
			客户端代码(调用的类)尽量依赖(使用)抽象。
			抽象不应该依赖细节,细节应该依赖抽象。

具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。 我们知道,依赖一定会存在于类与类、模块与模块之间。当两个模块之间存在紧密的耦合关系时,最好的方法就是使用继承定义一个抽象的概念,使得高层的类调用抽象类,而底层类实现抽象的具象化,以此来有效控制耦合关系,达到依赖于抽象的设计目标。

组合复用原则
			如果仅仅为了代码复用优先选择组合复用,而非继承复用。
			组合的耦合性相对继承低。

使用耦合度相对较低的关联方式替换耦合度最高的泛化方式
在面向编程中讲究高内聚,低耦合,这样的程序才是完美的程序。
继承只用作功能和数据的复用,以及同名功能的扩展,因为继承破坏了类的封装性,耦合度过高,类与类之间到底依赖性过高,灵活性较低,组合则恰恰相反,保证了类的封装性,降低了耦合度,灵活性高,但新功能的拓展实现没有继承方便。

里式替换原则
			父类出现的地方可以被子类替换,在替换后依然保持原功能。
			子类要拥有父类的所有功能。
			子类在重写父类方法时,尽量选择扩展重写,防止改变了功能。

里式替换的主要思想就是只要父类可以被调用,子类就一定要代替父类被调用。这种情况并不是说父亲没有意义,相反的,里式替换进一步要求父类尽可能不要存在太具体的功能,能抽象就尽量抽象,任何的修改都完全依靠子类来补充和修改,从而进一步实现开闭原则。

任何基类可以出现的地方,子类一定可以出现。 里氏替换原则(LSP)是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

迪米特法则
			不要和陌生人说话。
			类与类交互时,在满足功能要求的基础上,传递的数据量越少越好。因为这样可能降低耦合度。

它的主要思想就是类与类之间尽可能不要有太多的关联,当一个类需要变化时,对其他类基本没有影响。

注:待修改

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值