五.面向对象编程

Posted huiguizhe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五.面向对象编程相关的知识,希望对你有一定的参考价值。

1.面向过程与面向对象

1.1面向过程(Procedure Oriented 简称PO :像C语言):

    面向过程注重过程的。当解决一个问题的时候,面向过程会把事情拆分成: 一个个函数和数据(用于方法的参数) 。然后按照一定的顺序,执行完这些方法(每个方法看作一个个过程),等方法执行完了,事情就搞定了。

1.2面向对象(Object Oriented简称OO :像C++,JAVA等语言):

    面向对象注重对象的。当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决。

1.3两者的区别

    面向对象是将事物高度抽象化,而面向过程是一种自顶向下的编程

1.4两者各自的优缺点

面向过程

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。 
缺点:没有面向对象易维护、易复用、

面向对象

      优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护 
      缺点:性能比面向过程低

2.面向对象编程

1.1 对象(Object) :

    一个对象是一个类实例化后的实例,可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性

1.2 类(class):

    一个共享相同结构和行为的对象的集合。类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。举例来说,“狗”这个类会包含狗的一切基础特征,

  例如它的孕育、毛皮颜色和吠叫的能力。类可以为程序提供模版和结构。一个类的方法和属性被称为“成员”

1.3  封装(encapsulation):

     目的是隐藏实现细节,使代码模块化

    第一层意思:将数据和操作捆绑在一起,创造出一个新的类型的过程。
    第二层意思:将接口与实现分离的过程。
1.4   继承:
        目的是实现代码的重用,类之间的关系,在这种关系中,一个类共享了一个或多个其他类定义的结构和行为。继承描述了类之间的“是一种”关系。
    子类可以对基类的行为进行扩展、覆盖、重定义
1.5 多态
      一个接口多种实现,目的是实现接口重用。类型理论中的一个概念,一个名称可以表示很多不同类的对象,这些类和一个共同超类有关。
 因此,这个名称表示的任何对象可以以不同的方式响应一些共同的操作集合

 

1.6 五大基本原则:SPR, OCP, LSP, DIP, ISP

   1.6.1  单一职责原则SRP(Single Responsibility Principle)

    是指一个类的功能要单一,不能包罗万象。如同一个人一样,分配的工作不能太多,否则一天到晚虽然忙忙碌碌的,但效率却高不起来。

  1.6.2  开放封闭原则OCP(Open-Close Principle)

    一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。

  1.6.3  里式替换原则LSP(the Liskov Substitution Principle LSP)

    子类应当可以替换父类并出现在父类能够出现的任何地方。比如:公司搞年度晚会,所有员工可以参加抽奖,那么不管是老员工还是新员工,也不管是总部员工还是外派员工,都应当可以参加抽奖,否则这公司就不和谐了。

  1.6.4  依赖倒置原则DIP(the Dependency Inversion Principle DIP)

    具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,这个时候,B不应当直接使用A中的具体类: 而应当由B定义一抽象接口,并由A来实现这个抽象接口,B只使用这个抽象接口:这样就达到了依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能 造成循环依赖。一个常见的问题就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时同样要直接包含到A的cpp文件。

  1.6.5  接口分离原则ISP(the Interface Segregation Principle ISP)

    模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来

  1.6.6   耦合

    简单地说,软件工程中对象之间的耦合度就是对象之间的依赖性。指导使用和维护对象的主要问题是对象之间的多重依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。

有软硬件之间的耦合,还有软件各模块之间的耦合。
耦合性是程序结构中各个模块之间相互关联的度量。它取决于各个模块之间的接口的复杂程度、调用模块的方式以及哪些信息通过接口。

耦合可以分为以下几种,它们之间的耦合度由高到低排列如下:

  • 内容耦合。当一个模块直接修改或操作另一个模块的数据时,或一个模块不通过正常入口而转入另一个模块时,这样的耦合被称为内容耦合。内容耦合是最高程度的耦合,应该避免使用之。
  • 公共耦合。两个或两个以上的模块共同引用一个全局数据项,这种耦合被称为公共耦合。在具有大量公共耦合的结构中,确定究竟是哪个模块给全局变量赋了一个特定的值是十分困难的。
  • 外部耦合 。一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
  • 控制耦合 。一个模块通过接口向另一个模块传递一个控制信号,接受信号的模块根据信号值而进行适当的动作,这种耦合被称为控制耦合。
  • 标记耦合 。若一个模块A通过接口向两个模块B和C传递一个公共参数,那么称模块B和C之间存在一个标记耦合。
  • 数据耦合。模块之间通过参数来传递数据,那么被称为数据耦合。数据耦合是最低的一种耦合形式,系统中一般都存在这种类型的耦合,因为为了完成一些有意义的功能,往往需要将某些模块的输出数据作为另一些模块的输入数据。
  • 非直接耦合 。两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。

总结
耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。

1.6.7 内聚与耦合

     内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展。内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系。
耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。 程序讲究的是低耦合,高内聚。就是同一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依存度却要不那么紧密。
内聚和耦合是密切相关的,同其他模块存在高耦合的模块意味着低内聚,而高内聚的模块意味着该模块同其他模块之间是低耦合。在进行软件设计时,应力争做到高内聚,低耦合。

3 类的实例

3.1类的属性和方法,构造函数

技术图片
class Rloe():
    a = 123#类变量
    def __init__(self,name,role,weapon,life_value=100, money= 15000):
        #构造函数,在实例化时初始化类
        self.name = name#实例变量(静态属性),赋给了实例,作用域是实例本事(r1)
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money
    def shot(self):#类的方法,(动态属性)
        print("shooting..")
    def got_shot(self):
        print("ah....,I got shot....")
    def buy_gun(self,gun_name):
        print("%s just bought %s" %(self.name,gun_name))

r1 = Rloe("alex","police","ak47")#实例化一个对象,也叫Role的实例
# r1.buy_gun("ak47")
# r1.bullet = True#添加一个属性
# print(r1.bullet)
# del r1.weapon#删除一个属性
# print(r1.weapon)
Rloe.a = "adc"
print(r1.a)
View Code

3.2 类的私有属性和私有方法,析构函数

技术图片
class Rloe():
    a = 123#类变量,共用属性,节省开销
    def __init__(self,name,role,weapon,life_value=100, money= 15000):
        #构造函数,在实例化时初始化类
        self.name = name#实例变量(静态属性),赋给了实例,作用域是实例本事(r1)
        self.role = role
        self.weapon = weapon
        self.__life_value = life_value#变为了私有属性
        self.money = money
    # def __del__(self):#析构函数:在实例释放、销毁的时候自动执行的,通常用于做一些收尾工作,如关闭一些数据库链接,关闭文件
    #     print("%s 彻底死了。。。"%self.name)
    def life(self):#内部调用
        print("%s 的生命是%s"%(self.name,self.__life_value))
    def shot(self):#类的方法,(动态属性)
        print("shooting..")
    def __got_shot(self):#私有方法
        print("ah....,I got shot....")
    def buy_gun(self,gun_name):
        print("%s just bought %s" %(self.name,gun_name))

r1 = Rloe("alex","police","ak47")
# r1.shot()
# print(r1.__life_value)#变为私有属性后无法查看和修改,但能通过调用内部方法来查看
r1.life()
r1.__got_shot()#私有方法也无法调用
View Code

3.3   继承

单继承

   继承和重构父类方法

技术图片
class Pople():

    def __init__(self,name,age):
        self.name = name
        self.age = name
    def eat(self):
        print("%s is eating "%self.name)

    def sellp(self):
        print("%s is sleeping......"%self.name)

    def talk(self):
        print("%s is taking..."%self.name)

class Man(Pople):
    # def sellp(self):#将覆盖父类中的方法
    #     print("%s is  go to sleeping......"%self.name)
    def sellp(self):
        Pople.sellp(self)#重构父类方法,加了新功能
        print("%s is go to sleeping......"%self.name)

class Woman(Pople):

    def get_birth(self):
        print("%s is born a baby...."%self.name)

m1 = Man("alex",22)
m1.eat()
m1.sellp()
w1 = Woman("ming",23)
w1.get_birth()
View Code

    继承和重构构造函数,添加属性

技术图片
class Pople():

    def __init__(self,name,age):
        self.name = name
        self.age = name
    def eat(self):
        print("%s is eating "%self.name)

    def sellp(self):
        print("%s is sleeping......"%self.name)

    def talk(self):
        print("%s is taking..."%self.name)

class Man(Pople):
    def __init__(self,name,age,money):#重构构造函数,添加属性
        # Pople.__init__(self,name,age)#调用继承父类属性
        super(Man,self).__init__(name,age)#另一种调用方法
        self.money = money#添加新属性
        print("%s 一出生就有%s¥"%(self.name,self.money))
    # def sellp(self):#将覆盖父类中的方法
    #     print("%s is  go to sleeping......"%self.name)
    def sellp(self):
        Pople.sellp(self)#重构父类方法,加了新功能
        print("%s is go to sleeping......"%self.name)

class Woman(Pople):

    def get_birth(self):
        print("%s is born a baby...."%self.name)

m1 = Man("alex",22,10)
m1.eat()
m1.sellp()
w1 = Woman("ming",23)
w1.get_birth()
View Code

多继承

技术图片
class Pople(object):#新式类与经典类的区别在于类的继承上
# class Pople:#经典类

    def __init__(self,name,age):
        self.name = name
        self.age = name
    def eat(self):
        print("%s is eating "%self.name)

    def sellp(self):
        print("%s is sleeping......"%self.name)

    def talk(self):
        print("%s is taking..."%self.name)

class Relation(object):
    def make_friend(self,obj):
        print("%s is making friends with %s"%(self.name,obj.name))

class Man(Pople,Relation):
    def __init__(self,name,age,money):#重构构造函数,添加属性
        # Pople.__init__(self,name,age)#调用继承父类属性
        super(Man,self).__init__(name,age)#另一种调用方法
        self.money = money#添加新属性
        print("%s 一出生就有%s¥"%(self.name,self.money))
    # def sellp(self):#将覆盖父类中的方法
    #     print("%s is  go to sleeping......"%self.name)
    def sellp(self):
        Pople.sellp(self)#重构父类方法,加了新功能
        print("%s is go to sleeping......"%self.name)

class Woman(Pople,Relation):

    def get_birth(self):
        print("%s is born a baby...."%self.name)

m1 = Man("alex",22,10)
# m1.eat()
# m1.sellp()
w1 = Woman("ming",23)
# w1.get_birth()
m1.make_friend(w1)
View Code

 p3继承都是按广度优先

技术图片
class A:#p3都是广度优先,p2经典类是按深度优先来继承,新式类按广度优先
    def __init__(self):
        print("A")
class B(A):
    pass
    # def __init__(self):
    #     print("B")

class C(A):
    pass
    # def __init__(self):
    #     print("C")

class D(B,C):
    pass
    #  def __init__(self):
    #     print("D")
D()
View Code
技术图片
class School(object):
    def __init__(self,name,addr):
        self.name = name
        self.addr = addr
        self.students = []
        self.teachers = []
        self.staffs = []

    def enroll(self,stu_obj):#办理
        print("为学员%s 办理注册手续"%stu_obj.name)
        self.students.append(stu_obj)
    def hire(self,stu_obj):
        self.staffs.append(stu_obj)
        print("雇用新员工%s"%stu_obj.name)

class SchoolMember(object):#备用
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def tell(self):
        pass


class Teacher(SchoolMember):
    def __init__(self,name,age,sex,salary,course):
        super(Teacher,self).__init__(name,age,sex)
        self.salary = salary
        self.course = course
    def tell(self):
        print(‘‘‘--info of Teacher:%s--
              Name:%s
              Age:%s
              Sex:%s
              Salary:%s
              Course:%s
              ‘‘‘%(self.name,self.name,self.age,self.sex,self.salary,self.course))
    def teach(self):
        print("%s is teaching cours [%s]"%(self.name,self.sex))
class Student(SchoolMember):
    def __init__(self,name,age,sex,stu_id,grade):
        super(Student,self).__init__(name,age,sex)
        self.stu_id = stu_id
        self.grade = grade
    def tell(self):
        print(‘‘‘--info of Student:%s--
              Name:%s
              Age:%s
              Sex:%s
              Stu_id:%s
              Grade:%s
              ‘‘‘%(self.name,self.name,self.age,self.sex,self.stu_id,self.grade))
    def pay_tution(self,amout):
        print("%s has paid tution for $%s"%(self.name,amout))

school = School("老男孩IT","沙河")
t1 = Teacher("Oldbay",56,"man",10000,"java")
s1 = Student("01student",23,"man","110","1")
s1.tell()
t1.tell()
school.enroll(s1)
school.hire(t1)
View Code

3.4 多肽(一个接口多种实现)

技术图片
‘‘‘
class Animal(object):
    def __init__(self,name):
        self.name = name

    def talk(self):
        pass


class Cat(Animal):
    def talk(self):
        print( "Meow!")
class Dog(Animal):
    def talk(self):
        print("Woof! Woof!")

def animal(obj):
    obj.talk()

d1 = Dog("hua")#要调用方法,要用两个接口,d1和c1
# d1.talk()
c1 = Cat("hua")
# c1.talk()
animal(c1)#用一个接口就实现了调用两个方法
animal(d1)
‘‘‘
class Animal(object):
    def __init__(self,name):
        self.name = name

    def talk(self):
        pass
    @staticmethod#装饰器
    def animal(obj):
        obj.talk()


class Cat(Animal):
    def talk(self):
        print( "Meow!")
class Dog(Animal):
    def talk(self):
        print("Woof! Woof!")



d1 = Dog("hua")#要调用方法,要用两个接口,d1和c1
# d1.talk()
c1 = Cat("hua")
# c1.talk()
Animal.animal(c1)#用一个接口就实现了调用两个方法
Animal.animal(d1)
View Code

 3.4 静态方法

技术图片
#静态方法 ,在静态方法中是访问不了类的方法
class Dog(object):
    def __init__(self,name):
        self.name = name
    @staticmethod#用它,相当于把eat方法截取出来,跟Dog类没关系了,就没有self了
    def eat(self,food):
        print("%s is eating %s"%(self.name,food))

d = Dog("ming")
d.eat("包子")
View Code

    类方法

技术图片
#类方法
class Dog(object):
    name = "liu"
    def __init__(self,name):
        self.name = name
    @classmethod#类方法,只能访问类变量,不能访问实例变量
    def eat(self):
        print("%s is eating %s"%(self.name,"dd"))

d = Dog("ming")
d.eat()
View Code

   属性方法

技术图片
class Dog(object):

    def __init__(self,name):
        self.name = name
        self.__food = None
    @property#属性方法,把一个方法变为一个静态属性
    def eat(self):
        print("%s is eating %s"%(self.name,self.__food))

    @eat.setter
    def eat(self,food):
        print("set to food:",food)
        self.__food =food

    # @eat.deleter#内部删除
    # def eat(self, food):
    #     del self.__food = food
    #     print("删完了")


d = Dog("ming")
d.eat
d.eat = "baozi"
# del eat#无法正规删除
View Code
技术图片
#静态方法应用
#1.连接航空公司API查询
#2.对查询结果进行解析
#3.返回结果给你的用户
class Flight(object):
    def __init__(self,name):
        self.flight_name = name

    def checking_status(self):
        print("checking flight %s status "%self.flight_name)#相当于调api,并返回结果
        return 1
    @property
    def flight_status(self):
        status = self.checking_status()
        if status == 0:
            print("flight got canceled...")
        elif status == 1:
            print("flight is arrived....")
        elif status == 2:
            print("flight has departured already...")
        else:
            print("connot confirm the flight status....,please check")


f = Flight("CA980")
f.flight_status
View Code

3.5 其他方法

技术图片
class Dog(object):
    """这个类是描述狗这个对象的"""#描述字符
    def __init__(self,name):
        self.name = name

    def eat(self,food):
        print("%s is eating %s"%(self.name,food))

d = Dog("ming")
d.eat("包子")
1 # print(Dog.__doc__)#打印描述字符
print(d.__module__)
print(d.__class__)
2 # __module__表示当前操作在哪个模块,
3 # __class__ 表示当前操作的对象的类是什么
class Dog(object):
    """这个类是描述狗这个对象的"""#描述字符
    def __init__(self,name):
        self.name = name

    def eat(self,food):
        print("%s is eating %s"%(self.name,food))
    def __call__(self, *args, **kwargs):#4  __call__方法
        print("running call",args,kwargs)

d = Dog("ming")
d(1,2,3,name="alex")
5.#__dict__查看类和对象中的所有成员
print(Dog.__dict__)#查看类中的所有属性
print(d.__dict__)#查看实例属性
6.class Dog(object):
    """这个类是描述狗这个对象的"""#描述字符
    def __init__(self,name):
        self.name = name

    def eat(self,food):
        print("%s is eating %s"%(self.name,food))

    def __str__(self):#
        return "<obj:%s>"%self.name
d = Dog("ming")
print(d)
7.创建类
def func(self):
    print("hello %s"%self.name)


def __init__(self, name):
    self.name = name


# Foo = type("Foo",(object,),{"key":func})#创建一个类Foo
Foo = type("Foo", (object,), {"key": func,
                              "__init__":__init__})  # 合在一起创建一个类
f=Foo("alex")
f.key()
print(type(Foo))
8.#原类的创建,
class MyType(type):
    def __init__(self,what,bases=None,dict=None):
        print("--MyType init--")
        super(MyType,self).__init__(what,bases,dict)

    def __call__(self, *args, **kwargs):
        print("--MyType call--")
        obj = self.__new__(self,*args,**kwargs)#调用了new

        self.__init__(obj,*args,**kwargs)#调用了init


class Foo(object):
    __metaclass__ = MyType

    def __init__(self,name):
        self.name = name
        print("Foo-- init__")

    def __new__(cls, *args, **kwargs):#new实例化了对象(代替了init),创建了实例,cls相当于Foo
        print("Foo--new--")
        return object.__new__(cls)#继承父类的new方法

Foo("alex")
View Code

 3.6  反射

通过字符串映射或修改程序运行时的状态、属性、方法

技术图片
# gatattr
# setattr
# hasattr
# delattr
def bulk(self):
    print("%s is take"%self.name)
class Dog(object):

    def __init__(self,name):
        self.name = name

    def eat(self,food):
        print("%s is eating...."%self.name,food)

d = Dog("hua")
choice = input(">>:").strip()
# d.choice#无法调用
# print(hasattr(d,choice))#判断d中是否有choice这个方法,根据映射,有则返回True
# print(getattr(d,choice))#调用内存地址
# print(getattr(d,choice)())#显示内容

if hasattr(d,choice):
    func = getattr(d,choice)
    func("包子")
# if hasattr(d,choice):
#     delattr(d,choice)

else:
    # setattr(d,choice,bulk)#d.choice = bulk
    # d.talk(d)#调用要用talk
    setattr(d,choice,None)#加入一个静态属性
    print(getattr(d,choice))#可以直接返回
    
# print(d.name)
View Code
技术图片
# mod = __import__("lib.aa")#mod = lib#动态加载lib下的模块aa
# print(mod.aa.C().name)
import importlib
aa = importlib.import_module("lib.aa")#直接导入aa
print(aa.C().name)
View Code

 

3.7  自定义异常

技术图片
class AlexException(Exception):
    def __init__(self,msg):
        self.message = msg

    def __str__(self):
        return  self.message #返回值

try:
    raise AlexException("我的异常")
except AlexException as e:
    print(e)
View Code
技术图片
#断言
a = "aa"
assert type(a) is str#相当于判断
print("你输入了一个字符串")
View Code

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

以上是关于五.面向对象编程的主要内容,如果未能解决你的问题,请参考以下文章

五.面向对象编程

面向面试编程代码片段之GC

面向对象简介

面向对象编程思想2s

五java面向对象编程_3

Scala的面向对象与函数编程