博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DAY19 面向对象三大特性之多态、封装
阅读量:4946 次
发布时间:2019-06-11

本文共 4605 字,大约阅读时间需要 15 分钟。

面向对象三大特性之:多态

  多态:指的是一类事物有多种形态。

  例如:动物具有多种形态。

import abcclass Animal(metaclass=abc.ABCMeta):  #同一类事物:动物    @abc.abstractmethod    def talk(self):        passclass People(Animal):   #动物的形态之一:人    def talk(self):        print('say hello')class Dog(Animal):      #动物的形态之一:狗    def talk(self):        print('barking')class Cat(Animal):    #动物的形态之一:猫    def talk(self):        print('miao')

多态性

  什么是多态动态绑定?(在继承的背景下使用,也称为多态性。)

  在面向对象方法中一般这样表述多态性:

  -----> 向不同的对象发送同一条消息,不同的对象在接受时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数。不同的行为就是指不同的实现,即执行不同的函数。

  -----> 换句人话说,就是在子类和父类中有同名的方法,接受相同的方法调用,都执行自己的同名方法,表现出不一样的行为。

import abcclass Animal(metaclass=abc.ABCMeta):  #同一类事物:动物    @abc.abstractmethod    def talk(self):        passclass People(Animal):   #动物的形态之一:人    def talk(self):        print('say hello')class Dog(Animal):      #动物的形态之一:狗    def talk(self):        print('barking')class Cat(Animal):    #动物的形态之一:猫    def talk(self):        print('miao')p = People()d = Dog()c = Cat()p.talk()d.talk()c.talk()>>>say hellobarkingmiao

鸭子类型(duck Typing)

  在程序设计中,鸭子类型是一种动态类型的一种风格。python崇尚鸭子类型,即“如果看起来像,叫声像而且走路像鸭子的,那么它就是鸭子。”

  例子一:在java语言中,定义一个函数,传递参数的类型必须得到控制,需要定义一个类来定义这些参数的数据类型,参数必须都继承这个类。换成python类型,例如:内置函数len()中的参数,可以是字符串,容器类型,iterator类型。因为这些数据类型的类中都有一个__len__()方法,并没有像java一样定义一个类用来继承,而是通过模糊的概念,并不是通过明确的继承来实现多态,认为拥有__len__()方法的就可以当做参数,符合鸭子类型。

 

面向对象三大特性之:封装

   封装:隐藏对象的属性以及实现方法,仅对外提供公共的访问方法。

  封装的优点:

    (1)将变化隔离

    (2)便于使用

    (3)提高安全性

  封装的原则:

    (1)将不需要对外提供的内容隐藏起来。

    (2)把属性都隐藏起来,提供一个公共访问的接口来对其进行访问。

广义的封装和狭义的封装

  (1)广义的封装:是为了只有这个类的对象才能够使用定义在类中的方法。

class 类名:    def func1(self):pass    def func2(self):pass    def func3(self):pass

  (2)狭义的封装:把一个名字藏在类中

  ##### 私有静态变量/私有对象属性/私有方法 #####

  在python中用双下划线__开头的方式将属性隐藏起来(设置成私有的)

  为什么要定义一个私有变量?

  (1)不想让你看到这个值。

  (2)不想让你修改这个值。

  (3)想让你在修改这个值得时候有一些限制。

  (4)有些属性或者方法不希望被子类继承。

  ##### 私有静态变量/私有对象属性/私有方法 #####

私有变量

  一般来说类中的属性就应该是共享的,但是语法上可以把类的属性设置成私有的。

#其实类中的__私有属性,都只是一个变形,变形为“_类名__属性”#一。设置私有属性class A:    __N = 0 #类的数据属性就应该是共享的,但是语法上是可以把类的属性设置成私有的。print(A._N)  #在类的外部就不能引用私有的静态变量>>>AttributeError: type object 'A' has no attribute '_N'#二。但是谨记,都只是变形。print(A.__dict__)>>>{'__module__': '__main__', '_A__N': 0, '__dict__': 
, '__weakref__':
, '__doc__': None}#通过__dict__方法,可以巧妙地打破类的外部不能访问私有属性,但是这种方法被约定俗成的禁止了。print(A.__dict__['_A__N'])>>>0
#其实这仅仅这是一种变形操作#类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:class A:    __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N    def __init__(self):        self.__X=10 #变形为self._A__X    def __foo(self): #变形为_A__foo        print('from A')    def bar(self):        self.__foo() #只有在类内部才可以通过__foo的形式访问到.

  总结:

  (1)类中定义的私有变量只能在类的内部使用,如:self.__x,其实已经变形为_类名__x

  (2)这种变形其实是针对外部的变形,令外部无法通过self.__x的方式访问到私有方法。

  (3)在子类中定义__x是无法覆盖父类中的__x属性的,因为在子类中定义就会变形为"_子类__x",在父类中"_父类__x"。

私有方法

  在继承中,父类如果不想让子类覆盖自己的方法,可以把方法设置成私有方法。

#正常情况>>> class A:...     def fa(self):...         print('from A')...     def test(self):...         self.fa()           #看self代表谁... >>> class B(A):...     def fa(self):...         print('from B')... >>> b=B()>>> b.test()from B #把fa定义成私有的,即__fa>>> class A:...     def __fa(self):     #在定义时就变形为_A__fa...         print('from A')...     def test(self):...         self.__fa()     #只会与自己所在的类为准,即调用_A__fa... >>> class B(A):...     def __fa(self):...         print('from B')... >>> b=B()>>> b.test()from A

内置函数补充之:property

  property是一个装饰器,它的作用是将一个方法伪装成一个属性。

class Student:    def __init__(self,name,age):        self.__name = name        self.age = age    @property     #将一个方法伪装成一个属性    def name(self):        return self.__namezhuge = Student('诸葛',20)print(zhuge.name)>>>诸葛

  为什么要用property?

   将一个类的函数定义成一个属性后,对象在去使用obj.name的时候,根本不会想到这个是经过函数运算后返回的,遵循了统一访问的原则。

ps:面向对象中封装的三大方式:

 【public】:这种就是对外公开,不封装。

 【protected】:这种封装方式就是对外不公开,但是对子类公开。

  【private】:这种封装方式就对谁的不公开

在python中并没有在语法上把它们三种都内建到class机制中,在c++里面一般会把所有的数据都设置成私有的,然后提供set和get方法去修改和获取,在python中可以通过property去实现。

 

class Foo:    def __init__(self,val):        self.__NAME= val    #将所有数据属性都转化为私有属性存起来。    @property    def name(self):        return self.__NAME    @name.setter    def name(self,value):        if not isinstance(value,str):            raise TypeError('%s must be str'%value)        self.__NAME = value  # 通过类型检测后,将值value存放到真实的位置self.__NAME    @name.deleter    def name(self):        raise TypeError('can not delete')f = Foo('egon')# print(f.name)   #通过name函数返回self.__NAME# f.name = 10      #TypeError: 10 must be strdel f.name         #TypeError: can not delete

 

  property总结:

 (1)一个静态属性property本质就是实现了get,set,delete三种方法。

 (2)只有在属性xxx定义了property后,才能使用xxx.setter,xxx.deleter。

 

转载于:https://www.cnblogs.com/hebbhao/p/9555340.html

你可能感兴趣的文章
python合并多表或两表数据
查看>>
第一个python作业题目以及代码
查看>>
【Android】用Cubism 2制作自己的Live2D——官方App样例源码学习(2)!
查看>>
利用锚点制作简单索引效果
查看>>
Photoshop
查看>>
项目练习计划
查看>>
Xshell远程登录
查看>>
@RequestParam与@PathVariable的区别
查看>>
C语言之break和continue
查看>>
jquery.form.js使用
查看>>
C#异常操作
查看>>
学习笔记43—Linux基础集
查看>>
3.5-杂项②
查看>>
用 Python 脚本实现对 Linux 服务器的监控
查看>>
ubuntu12.04安装日记
查看>>
leetcode - One Edit Distance
查看>>
Android getResources的作用和须要注意点
查看>>
[C++] 获取IE代理server的账号password
查看>>
WINHTTP的API接口说明
查看>>
C语言中可变参数函数实现原理
查看>>