zoukankan      html  css  js  c++  java
  • 面向对象基础部分及模块

    一、面向对象基础

    面向对象名词解释:

    • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

    • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

    • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。

    • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

    • 实例变量:定义在方法中的变量,只作用于当前实例的类。

    • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

    • 实例化:创建一个类的实例,类的具体对象。

    • 方法:类中定义的函数。(方法属于类,不属于实例)

    • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

    二、面向对象的特性:

    封装

    封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

    封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

    第一步:将内容封装到某处

    class1 SQLHELPer:
        def __init__(self,a1,a2,a3):#成为构造方法,根据类创建的对象自动执行
            self.hhost = a1
            self.uusername = a2
            self.pwd = a3
    
        def fetch(self):
            print(self.hhost)
            print(self.uusername)
            print(self.pwd)
        def create(self,sql):
            pass
        def remove(self,nid):
            pass
        def modify(self,name):
            pass
    #根据类SQLHELPer创建对象
    #自动执行SQLHELPer 的__init__方法
    obj = SQLHELPer()
    obj.hhost = "c1.salt.com"
    obj.uusername = "Jason"
    obj.pwd = "123"
    obj1 = SQLHELPer('abc.com','jack','234')

    self 是一个形式参数,当执行obj = SQLHELPer()时,self 等于 obj

                                 当执行obj1 = SQLHELPer('abc.com','jack','234')时,self 等于 obj1

    所以,内容其实被封装到了对象 obj 和 obj1 中,每个对象中都有 a1,a2和 a3 属性,在内存里类似于下图来保存。

     

    第二步:从某处调用被封装的内容

    调用被封装的内容时,有两种情况:

    • 通过对象直接调用
    • 通过self间接调用

    1、通过对象直接调用被封装的内容

    上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名

    class Foo:
     
        def __init__(self, name, age):
            self.name = name
            self.age = age
     
    obj1 = Foo('wupeiqi', 18)
    print obj1.name    # 直接调用obj1对象的name属性
    print obj1.age     # 直接调用obj1对象的age属性
     
    obj2 = Foo('alex', 73)
    print obj2.name    # 直接调用obj2对象的name属性
    print obj2.age     # 直接调用obj2对象的age属性
    

     2、通过self间接调用被封装的内容

    执行类中的方法时,需要通过self间接调用被封装的内容

    class Foo:
      
        def __init__(self, name, age):
            self.name = name
            self.age = age
      
        def detail(self):
            print self.name
            print self.age
      
    obj1 = Foo('wupeiqi', 18)
    obj1.detail()  # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18
      
    obj2 = Foo('alex', 73)
    obj2.detail()  # Python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78
    

     综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

    继承

    面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

    通过继承创建的新类称为“子类”或“派生类”。

    被继承的类称为“基类”、“父类”或“超类”。

    继承的过程,就是从一般到特殊的过程。

    要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。

    在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

    继承概念的实现方式有三类:实现继承、接口继承和可视继承。

    Ø         实现继承是指使用基类的属性和方法而无需额外编码的能力;
    Ø         接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;
    Ø         可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。

    在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。

    抽象类仅定义将由子类创建的一般属性和方法。

    OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

    class Role(object):
        def __init__(self, name):
            self.name = name
        def get_name(self):
            return self.name
    class Teacher(Role):
        def __init__(self, name, course):
            '''
            如果父类已经有一个方法,子类也有一个同名的方法,就会覆盖掉父类的方法,专业术语叫做重写
            '''
            super(Teacher, self).__init__(name) # 通过super这种语法可以调用父类的方法和变量,这里调用父类的构造方法,初始化name
            self.course = course # 这个变量是父类所没有的
        def say(self): # 定义父类的
            print('My name is %s, i am a English teather' %self.name)
    if __name__ == '__main__':
        lisi = Teacher('lisi', 'English') # 定义Teacher的实例
        print(lisi.name) # name这个变量是子类通过继承的方式获取的
        print(lisi.get_name()) # 继承自父类的方法
        lisi.say() # 子类特有的方法
    

     所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

    注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。

    那么问题又来了,多继承呢?

    • 是否可以继承多个类
    • 如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?

    1、Python的类可以继承多个类,Java和C#中则只能继承一个类

    2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先广度优先

    深度优先

    class D:
        def bar(self):
            print('D.bar')
    
    class C():
        def bar(self):
            print('C.bar')
    
    
    class B(D):
        def bar2(self):
            print('B.bar')
    
    
    class A(B,C):
        def bar1(self):
            print('A.bar')
    
    a = A()
    a.bar()##D.bar
    # 执行bar方法时
    # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
    # 所以,查找顺序:A --> B --> D --> C 如下图
    # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    a.bar()
    
    

    广度优先

    class D(object):
        def bar(self):
            print('D.bar')
    
    class C(D):
        def bar(self):
            print('C.bar')
    
    
    class B(D):
        def bar2(self):
            print('B.bar')
    
    
    class A(B,C):
        def bar1(self):
            print('A.bar')
    
    a = A()
    # 执行bar方法时
    # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
    # 所以,查找顺序:A --> B --> C --> D 如下图
    # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    a.bar()##C.bar

     

    经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。

    经典类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错

    新式类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错

    注意:在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了

    ** Python3中默认均为广度优先

    多态

    多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
    那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
     

    三 类的定义(详细说明)

    class Foo(object): # Foo为类名,括号内的表示是这个类继承自哪个类,这里的object是所有类的基类,一个类可以继承自多个类
        '''
        类的说明文档,Python会自动将这里面内容赋值给类的变量__doc__
        '''
        class_var1 = 'var1' # 类的变量,它属于类本身,而不是类的对象,可以通过类名.变量名的方式进行调用,也可以对象.变量名调用,前提是,没有同名的实例变量
        def __init__(self, arg, arg2):
            '''
            初始化方法,有点类似于java语言的构造方法,在创建类的对象的时候自动调用
            :param var2: 参数,初始化方法也可以
            :return:
            '''
            self.var2 = arg # 对象的变量,属于对象不属于类,只能通过对象.变量名的方式调用
            self.__var3 = arg # 对象的变量,只能在内部调用,不能通过对象.变量名的方式调用,并且不能被继承
     
        def func1(self, arg):
            '''
            方法
            1、方法属于类(也就是在实例化的时候不会像对象的变量一样单独开辟内存空间)
            2、self表示类的对象本身,当我们通过对象名.方法()来调用的时候,解释器会自动将对象作为第一个参数传给方法,方法名.方法(对象名)
            :return:
            '''
            # 方法体,方法体可以通过self.关键字调用对象的变量和方法
            self.__var3 = arg # 方法可以调用私有变量和方法
     
        def __func2(self):
            '''
            私有方法,和私有变量一样,不能被继承和外部调用
            :return:
            '''
            pass
     
    class Foo2(Foo):
        def __init__(self, arg, arg2):
            '''
            1、这里调用了父类的初始化方法,特别注意由于“__变量名”表示的私有方法,
            2、这里尽管调用了父类的构造方法,__var3变量作为父类的私有方法,子类在没有重新定义之前依然没有这个变量,这点要特别注意
            :param arg:
            :param arg2:
            :return:
            '''
            super(Foo2, self).__init__(arg, arg2)
            self.__var3 = arg2 # 由于__var3是父类的私有方法,尽管调用了父类的初始化方法,子类依然不会有,所以依然需要重新定义
    

    ##参考文档

    1、金角大王博客:http://www.cnblogs.com/alex3714/articles/5188179.html

    2、银角大王博客:http://www.cnblogs.com/wupeiqi/articles/5017742.html

    3、 65年哥:http://www.cnblogs.com/zhangxiaxuan/p/5292691.html

    4. Eva_l:   http://www.cnblogs.com/Eva-J/p/5009377.html

     

  • 相关阅读:
    ORACLE函数介绍
    msdn的javascript文章转载
    baidu的高级搜索命令
    周杰伦 青花瓷 蒲公英的约定 我不配 彩虹 歌词和下载
    谷歌百度相争 新浪渔翁得利
    tomcat+jsp web运行环境搭建
    C#2008与.NET 3.5 高级程序设计读书笔记(24) LINQ API编程
    C#2008与.NET 3.5 高级程序设计读书笔记(16) 类型反射、晚期绑定和基于特性的编程
    C#2008与.NET 3.5 高级程序设计读书笔记(15) .NET程序集入门
    C#2008与.NET 3.5 高级程序设计读书笔记(25) WCF
  • 原文地址:https://www.cnblogs.com/jasonwang-2016/p/5614485.html
Copyright © 2011-2022 走看看