zoukankan      html  css  js  c++  java
  • 面向对象的三大特性

    • 封装

    • 多态

    • 继承

    封装 

       广义的封装 : 把方法和属性都封装在一个类里,定义一个规范来描述一类事物.
       狭义的封装 : 私有化 只能在类的内部访问
      __静态变量,私有方法 ,私有的对象属性,私有的类方法,私有的静态方法
      在内存中存储 _类名__名字
      为什么在类的内部可以使用双下划线访问 : 在类的内部使用,你就知道你在哪个类中
      在子类中可以访问访问父类的私有变量么?不行
      私有 : 不能在类的外部使用也不能被继承

    私有变量和私有方法

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

    私有变量

    #其实这仅仅这是一种变形操作
    #类中所有双下划线开头的名称如__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的形式访问到.
    
    #A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形

    这种自动变形的特点:

    1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果

    2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。

    3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

    这种变形需要注意的问题是:

    1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

    2.变形的过程只在类的内部生效,在定义后的赋值操作,不会变形

    私有方法

    3.在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

    #正常情况
    >>> class A:
    ...     def fa(self):
    ...         print('from A')
    ...     def test(self):
    ...         self.fa()
    ... 
    >>> 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

    封装与扩展性

    封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

    #类的设计者
    class Room:
        def __init__(self,name,owner,width,length,high):
            self.name=name
            self.owner=owner
            self.__width=width
            self.__length=length
            self.__high=high
        def tell_area(self): #对外提供的接口,隐藏了内部的实现细节,此时我们想求的是面积
            return self.__width * self.__length
    
    
    #使用者
    >>> r1=Room('卧室','egon',20,20,20)
    >>> r1.tell_area() #使用者调用接口tell_area
    
    
    #类的设计者,轻松的扩展了功能,而类的使用者完全不需要改变自己的代码
    class Room:
        def __init__(self,name,owner,width,length,high):
            self.name=name
            self.owner=owner
            self.__width=width
            self.__length=length
            self.__high=high
        def tell_area(self): #对外提供的接口,隐藏内部实现,此时我们想求的是体积,内部逻辑变了,只需求修该下列一行就可以很简答的实现,而且外部调用感知不到,仍然使用该方法,但是功能已经变了
            return self.__width * self.__length * self.__high
    
    
    #对于仍然在使用tell_area接口的人来说,根本无需改动自己的代码,就可以用上新功能
    >>> r1.tell_area()

    property属性

    装饰器函数,内置函数,帮助你将类中的方法伪装成属性,特性

    调用方法的时候不需要主动加括号
    让程序的逻辑性更合理
    @方法名.setter 装饰器,修改被property装饰的属性的时候会调用被这个装饰器装饰的方法,除了self之外还有一个参数,被修改的值
    @方法名.deleter 装饰器,当要删除被property装饰的属性的时候会调用被这个装饰器装饰的方法

    # class Circle:
    #     def __init__(self,r):
    #         self.r = r
    #         # self.area = 3.14*self.r**2
    #
    #     @property
    #     def area(self):   #  这个方法计算结果本身就是是一个属性,但是这个属性会随着这个类/对象的一些基础变量的变化而变化
    #         return 3.14*self.r**2
    
    # c = Circle(5)
    # print(c.area)
    # c.r = 10
    # print(c.area)
    
    # 偏其他语言 property+私有的 合用 ,这个时候更多的也会用到setter和deleter
    # class A:
    #     def __init__(self,name):
    #         self.__name = name
    #
    #     @property
    #     def name(self):
    #         return self.__name
    #
    #     @name.setter
    #     def name(self,new_name):
    #         if type(new_name) is str:
    #             self.__name = new_name
    #
    #     @name.deleter
    #     def name(self):
    #         del self.__name
    # a = A('alex')
    # a.name = 123
    # print(a.name)
    # del a.name   # 语法
    # print(a.name)

     classmethod

    类方法的装饰器 内置函数
    使用类名调用,默认传类名作为第一个参数
    不用对象命名空间中的内容,而用到了类命名空间中的变量(静态属性),或者类方法或静态方法

    # class Goods:
    #     __discount = 0.8
    #     def __init__(self,price):
    #         self.__price = price
    #     @property
    #     def price(self):
    #         return self.__price * Goods.__discount
    #     @classmethod
    #     def change_discount(cls,num):
    #         cls.__discount = num
    #
    # # 商场的程序
    # apple = Goods(10)
    # banana = Goods(15)
    # print(apple.price,banana.price)
    # Goods.change_discount(1)
    # print(apple.price,banana.price)

    staticmethod

    静态方法的装饰器 内置函数

    如果一个类里面的方法 既不需要用到self中的资源,也不用cls中的资源.

    相当于一个普通的函数
    但是你由于某种原因,还要把这个方法放在类中,这个时候,就将这个方法变成一个静态方法
    某种原因:
    你完全想用面向对象编程 ,所有的函数都必须写到类里
    某个功能确确实实是这个类的方法,但是确确实实没有用到和这个类有关系的资源

    # 学生 管理员
    # 课程 班级
    # class Person:
    #     @staticmethod
    #     def login():  # 动词 动作 属于某一个对象
    #         pass
    # class Student(Person):pass
    # class Manager(Person):pass
    # class Course:pass
    # class Classes:pass
    幻想毫无价值,计划渺如尘埃,目标不可能达到。这一切的一切毫无意义——除非我们付诸行动。
  • 相关阅读:
    [Err] 1064
    maven项目警告: Using platform encoding (UTF-8 actually) to copy filtered resources
    maven中引入oracle驱动报错Missing artifact com.oracle:ojdbc14:jar:10.2.0.4.0
    springMVC 中url后缀使用html,不能返回json数据,否则会报406错误
    网站并发量的计算方法
    win7旗舰版显示不了文件扩展名
    Java获取mysql数据库元数据
    spring中 context:property-placeholder 导入多个独立的 .properties配置文件
    Could not autowire field: private java.lang.Integer com.taotao.sso.service.impl.UserServiceImpl.SSO_
    linux Nginx服务开机自启
  • 原文地址:https://www.cnblogs.com/TodayWind/p/13916682.html
Copyright © 2011-2022 走看看