面向对象进阶
Posted liuhongshuai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象进阶相关的知识,希望对你有一定的参考价值。
1,组合
组合 在一个类中以另外一个类的对象作为数据属性,称为类的组合----> ‘有‘的关系
#组合 在一个类中以另外一个类的对象作为数据属性,称为类的组合 #圆形与圆环类 # from math import pi # class Circle: # def __init__(self,r): # self.r=r # def perimeter(self): # return 2*pi*self.r # def area(self): # return pi*self.r*self.r # class Ring: # def __init__(self,outside_r,inside_r): # self.outside_c=Circle(outside_r) # self.inside_c=Circle(inside_r) # def perimeter(self): # return self.outside_c.perimeter()+self.inside_c.perimeter() # def area(self): # return self.outside_c.area()-self.inside_c.area() # # ring=Ring(20,10) # print(ring.__dict__) # print(ring.perimeter()) # print(ring.area()) # class Birthday: # def __init__(self,year,month,day): # self.year=year # self.month=month # self.day=day # # class Course: # def __init__(self,course_name,period,price): # self.course_name=course_name # self.period=period # self.price=price # # # class Teacher: # def __init__(self,name,age,sex,birthday): # self.name=name # self.age=age # self.sex=sex # self.birthday=birthday # self.course=Course(‘python‘,‘6 month‘,‘19980‘) # # b=Birthday(2018,10,10) # alex=Teacher(‘alex‘,20,‘男‘,b) # print(alex.name) # print(alex.birthday) # print(alex.birthday.year) # print(alex.course.period) # class Birthday: # def __init__(self,year): # self.year=year # class Person: # def __init__(self,name): # self.name=name # # alex=Person(‘alex‘) # alex.birth=Birthday(2018) # print(alex.birth.year)
2,继承
继承 继承是基于抽象的结果 派生 对象有自己的属性和方法 通过继承建立了派生类与基类的关系 -----> ‘是‘的关系 继承的作用 减少代码的重用 提高代码可读性 规范编程模式
#继承 单继承 多继承 # class A:pass # class B:pass # class C(A):pass # class D(A,B):pass # print(A.__bases__)#默认继承object类 # print(C.__bases__) # print(D.__bases__) # class Animal: # def __init__(self,name,aggr): # self.name=name # self.aggr=aggr # def func(self): # print(‘animal‘) # # class Dog(Animal): # def __init__(self,name,aggr,kind): # # Animal.__init__(self,name,aggr)#方式1 # super().__init__(name,aggr)#方式2 新式类中 python3中都是新式类 # # super(__class__,self).__init__(name,aggr) # # super(Dog,self).__init__(name,aggr) # self.kind=kind #派生属性 # def func(self): # # Animal.func(self)#在子类中调用父类的方法 # super().func() # print(‘dog‘) # def bite(self): # print(‘汪汪汪‘)#派生方法 # # # jinba=Dog(‘jingba‘,200,‘jingba‘) # print(jinba.name) # print(jinba.kind) # jinba.func() # jinba.bite() # super(Dog,jinba).func() # print(jinba.__class__) # class Animal: # def __init__(self): # print(‘执行Animal.__init__‘) # self.func() # def func(self): # print(‘animal‘) # # class Dog(Animal): # def func(self): # print(‘dog‘) # jinba=Dog() # jinba.drink()#执行流程 -->本类-->父类 执行__init__中的内容-->找不到报错 #多继承 # class F:pass # class A(F):pass # class B(A):pass # class E(F):pass # class C(E):pass # class D(B,C):pass # print(D.mro())#查看继承顺序 广度优先F->B-->A-->C-->E-->F新式类 # class A(object): # def func(self): print(‘A‘) # # class B(A): # def func(self): # super().func() # print(‘B‘) # # class C(A): # def func(self): # super().func() # print(‘C‘) # # class D(B,C): # def func(self): # super().func() # print(‘D‘) # # b = D() # print(D.mro())#D B C A object # b.func()#A C B D
3,接口类与抽象类
抽象类与接口类 1.多继承问题 在继承抽象类的过程中,我们应该尽量避免多继承; 而在继承接口的时候,我们反而鼓励你来多继承接口 接口隔离原则: 使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。 2.方法的实现 在抽象类中,我们可以对一些抽象方法做出基础实现; 而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
# 实现接口类 接口继承 # from abc import abstractmethod,ABCMeta # # class Payment(metaclass=ABCMeta): # @abstractmethod # def pay(self,money):pass # # class Wechat(Payment): # def pay(self,money): # print(‘已经用微信支付了{}元‘.format(money)) # # class Alipay(Payment): # def pay(self,money): # print(‘已经用支付宝支付了{}元‘.format(money)) # # def pay(pay_obj,money):#统一支付入口 归一化设计 # pay_obj.pay(money) # # wechat=Wechat() # ali=Alipay() # wechat.pay(100) # pay(wechat,100) #接口类的多继承 # from abc import abstractmethod,ABCMeta # class Swim_Animal(metaclass=ABCMeta): # @abstractmethod # def swim(self):pass # # class Walk_Animal(metaclass=ABCMeta): # @abstractmethod # def walk(self):pass # # class Fly_Animal(metaclass=ABCMeta): # @abstractmethod # def fly(self):pass # # class OldYing(Fly_Animal,Walk_Animal): # def fly(self):pass # def walk(self):pass
#抽象类 一切皆文件 归一化 # from abc import abstractmethod,ABCMeta # # class All_file(metaclass=ABCMeta): # all_type=‘file‘ # @abstractmethod # def read(self):#定义抽象方法 无需实现功能 # ‘子类必须定义读功能‘ # with open(‘filename‘) as f: # pass # # def write(self): # ‘子类必须定义写功能‘ # pass # # # class Txt(All_file): # # pass # # # t=Txt()#报错 子类没有定义抽象方法#TypeError: Can‘t instantiate abstract class Txt with abstract methods read # # # class Txt(All_file):#子类 # def read(self): # print(‘文本数据的读取方法‘) # def write(self): # print(‘文本数据的写入方法‘) # # class Sata(All_file):#子类继承抽象类,但是必须定义read和write方法 # def read(self): # print(‘磁盘数据的读取方法‘) # def write(self): # print(‘磁盘数据的写入方法‘) # # class Process(All_file): # def read(self): # print(‘进程数据的读取方法‘) # def write(self): # print(‘进程数据的写入方法‘) # # t=Txt() # s=Sata() # p=Process() # #抽象类 一切皆文件 归一化 # print(t.all_type) # print(s.all_type) # print(p.all_type)
4,封装
封装 隐藏对象的属性和实现细节,仅对外提供公共访问方式 明确区分内外 好处 1. 将变化隔离; 2. 便于使用; 3. 提高复用性; 4. 提高安全性; 封装原则 1. 将不需要对外提供的内容都隐藏起来; 2. 把属性都隐藏,提供公共方法对其访问。
# 封装 # class Person: # __country=‘China‘#私有静态属性 # def __init__(self,name,pwd): # self.name=name # self.__pwd=pwd#私有属性 # def __get_pwd(self):#私有方法 # return self.__pwd#只要在类的内部使用私有属性,就会自动的带上_类名 # # def login(self): # return self.__get_pwd()#正常的方法调用私有的方法 # print(Person.__dict__)#{‘_Person__country‘: ‘China‘} # alex=Person(‘alex‘,‘alex3714‘) # print(alex._Person__pwd)#_类名__属性名 # print(alex.login())#正常的访问方式 # class Room: # def __init__(self,name,length,width): # self.__name=name # self.__length=length # self.__width=width # # def get_name(self): # return self.__name # def set_name(self,newName): # if type(newName) is str and newName.isdigit()==False: # self.__name=newName # else: # print(‘不合法的名字‘) # def area(self): # return self.__length*self.__width # # alex=Room(‘alex‘,100,100) # alex.set_name(‘yuan‘) # print(alex.get_name()) # print(alex.area()) # # class Foo: # __key=‘123‘ # class Son(Foo): # print(Foo.__key)#报错
5,多态与多态性
多态指的是同一种事物的多种状态
多态性指出了对象如何通过他们共同的属性和动作来操作及访问,而不需考虑他们具体的类。
#多态 多态性 # import abc # class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 # @abc.abstractmethod # def talk(self): # pass # # class People(Animal): # def talk(self): # print(‘Hello World‘) # # class Dog(Animal): # def talk(self): # print(‘汪汪汪‘) # # # p=People() # d=Dog() # #多态性 # p.talk() # d.talk()
6,property classsmethod staticmethod
# property # from math import pi # class Circle: # def __init__(self,radius): # self.radius=radius # @property # def perimeter(self): # return 2*pi*self.radius # @property # def area(self): # return pi*self.radius**2 # # c=Circle(5) # print(c.perimeter) # print(c.area) # class Goods: # discount=0.8 # def __init__(self,name,price): # self.name=name # self.__price=price # @property # def price(self): # return self.__price*self.discount # # apple=Goods(‘苹果‘,5) # print(apple.price) #属性 查看 修改 删除 # class Person: # def __init__(self,name): # self.__name=name # self.price=20 # @property # def name(self): # print(‘get的时候运行‘) # return self.__name # @name.setter # def name(self,new_name): # print(‘set的时候运行‘) # self.__name=new_name # @name.deleter # def name(self): # print(‘del的时候运行‘) # del self.__name # # # alex=Person(‘alex‘) # print(alex.name) # alex.name=‘yuan‘ # print(alex.name) # del alex.name # print(alex.__dict__)
# classmethod类方法 类直接调用 # class Foo: # role=‘person‘ # @classmethod # def func(cls): # print(cls.role) # Foo.func()
# staticmethod静态方法 # class Foo: # role=‘person‘ # @staticmethod # def func(a):#不需要传self # print(‘当普通方法用‘,a) # Foo.func(1) # f=Foo() # print(f.role) # f.func(1) # class Goods: # __discount=0.8 # def __init__(self,name,price): # self.name=name # self.__price=price # @property # def price(self): # return self.__price*self.__discount # @classmethod # def change_discount(cls,new_count):#修改折扣 # print(cls,cls.__discount) # cls.__discount=new_count # print(cls.__discount) # @staticmethod#staticmethod object # def text(x,y): # print(‘--->‘,x,y) # # print(Goods.__dict__) # apple=Goods(‘苹果‘,5) # print(apple.price) # Goods.change_discount(0.5) # print(apple.price) # Goods.text(1,2) # apple.text(1,2)
7,其他
面向对象 继承 封装 多态 #组合 一个类的对象是另一个类的属性 表达的是 什么有什么的关系 继承 父类(基类 超类) 子类(派生类) 多继承 新式类 广度优先(总体广度优先 单支深度优先) python3(只有新式类) 经典类 深度优先 python2(经典类与新式类共存 新式类要继承object) mro只在新式类中出现 super:只在python3 广度优先顺序查找父类 #接口类 python原生不支持 元类 type 接口类 方法不能实现 抽象类 方法可以有一定的实现 # 接口类 刚好满足接口隔离原则 面向对象开发的思想 本质是做代码规范用的 面向对象的开发规范 所有的接口类和抽象类都不能实例化 java不支持多继承 所以设计了接口 #python中没有接口类 有抽象类 python天然支持多态 多态:一类事物有多种形态 多态性 :同一操作作用于不同的对象 可以有不同的解释 产生不同的执行结果 python动态强类型语言 list tuple 有相似的__len__() 但是不是通过父类约束的 松耦合 鸭子类型 —— 不依赖父类的情况下实现两个相似的类中的同名方法 封装 隐藏对象的属性和实现细节 仅对外提供公共访问的方式 隐藏属性 不想让类的外部调用 不想让属性随意被改变 不被子类继承 # 当这个方法的操作只涉及静态属性的时候 就应该使用classmethod来装饰这个方法 # 如果一个函数 既和对象没有关系 也和类没有关系 那么就用staticmethod将这个函数变成一个静态方法 对象 存储属性和调用方法 设计模式 23种 单例模式 一个类只有一个对象
继承的用途 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能 接口类: 接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。 归一化:基于同一个接口实现的类,这些类产生的对象在使用时,从用法上来说都一样。 归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。 抽象类 只能被继承,不能被实例化 抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。 抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 几个名词 抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。 继承:子类继承了父类的方法和属性 派生:子类在父类方法和属性的基础上产生了新的方法和属性 多继承 新式类:广度优先 经典类:深度优先 多态 一类事物有多种形态 多态性 不考虑实例的情况下使用实例 鸭子类型 用相似的方法 但之间没有直接的继承关系 property classmethod staticmethod 面向对象的软件工程 面向对象分析 OOA 建立需求模型 面向对象设计 OOD 伪代码 流程图 面向对象编程 OOP 面向对象测试 OOT 面向对象维护 OOSM 面向对象常用术语 抽象/实现 抽象指对现实世界问题和实体的本质表现,行为和特征建模,建立一个相关的子集,可以用于 绘程序结构,从而实现这种模型。抽象不仅包括这种模型的数据属性,还定义了这些数据的接口。 对某种抽象的实现就是对此数据及与之相关接口的现实化(realization)。现实化这个过程对于客户 程序应当是透明而且无关的。 封装/接口 封装描述了对数据/信息进行隐藏的观念,它对数据属性提供接口和访问函数。通过任何客户端直接对数据的访问,无视接口,与封装性都是背道而驰的,除非程序员允许这些操作。作为实现的 一部分,客户端根本就不需要知道在封装之后,数据属性是如何组织的。在Python中,所有的类属性都是公开的,但名字可能被“混淆”了,以阻止未经授权的访问,但仅此而已,再没有其他预防措施了。这就需要在设计时,对数据提供相应的接口,以免客户程序通过不规范的操作来存取封装的数据属性。 注意:封装绝不是等于“把不想让别人看到、以后可能修改的东西用private隐藏起来” 真正的封装是,经过深入的思考,做出良好的抽象,给出“完整且最小”的接口,并使得内部细节可以对外透明 (注意:对外透明的意思是,外部调用者可以顺利的得到自己想要的任何功能,完全意识不到内部细节的存在) 合成 合成扩充了对类的 述,使得多个不同的类合成为一个大的类,来解决现实问题。合成 述了 一个异常复杂的系统,比如一个类由其它类组成,更小的组件也可能是其它的类,数据属性及行为, 所有这些合在一起,彼此是“有一个”的关系。 派生/继承/继承结构 派生描述了子类衍生出新的特性,新类保留已存类类型中所有需要的数据和行为,但允许修改或者其它的自定义操作,都不会修改原类的定义。 继承描述了子类属性从祖先类继承这样一种方式 继承结构表示多“代”派生,可以述成一个“族谱”,连续的子类,与祖先类都有关系。 泛化/特化 基于继承 泛化表示所有子类与其父类及祖先类有一样的特点。 特化描述所有子类的自定义,也就是,什么属性让它与其祖先类不同。 多态与多态性 多态指的是同一种事物的多种状态:水这种事物有多种不同的状态:冰,水蒸气 多态性的概念指出了对象如何通过他们共同的属性和动作来操作及访问,而不需考虑他们具体的类。 冰,水蒸气,都继承于水,它们都有一个同名的方法就是变成云,但是冰.变云(),与水蒸气.变云()是截然不同的过程,虽然调用的方法都一样 自省/反射 自省也称作反射,这个性质展示了某对象是如何在运行期取得自身信息的。如果传一个对象给你,你可以查出它有什么能力,这是一项强大的特性。如果Python不支持某种形式的自省功能,dir和type内建函数,将很难正常工作。还有那些特殊属性,像__dict__,__name__及__doc__ Java ps:面向对象的封装有三种方式: 【public】 这种其实就是不封装,是对外公开的 【protected】 这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开 【private】 这种封装对谁都不公开
以上是关于面向对象进阶的主要内容,如果未能解决你的问题,请参考以下文章