面向对象的程序设计

Posted liutianyuan

tags:

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

一、什么是面向对象

  面向对象编程是一种编程方式,使用“类”和“对象”来实现,所以,面向对象编程就是对“类”和“对象”的使用。

  面向对象编程 核心就是“对象”二字,“对象”是特征与技能的结合体。“类”则是一个模板,模板里可以包含多个方法(函数),方法可以实现各种功能。对象则是根据模板创建的实例,通过实例“对象”可以执行“类”中的方法,每个“对象”都拥有相同的方法,但是每个“对象”的数据可能并不相同

  优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

  缺点:

  1. 编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题。一些扩展性要求低的场景使用面向对象会徒增编程难度。

  2.无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果。

二、“类”’、“对象”和方法

在Python中,定义类是通过class关键字,class后面紧接着是类名,类名通常是大写开头的单词,紧接着是(‘要继承的类名‘),表示该类是从哪个类继承下来的,通常如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类,也可以不写。

class MyClass():             # 创建类
    def func(self):          # 定义方法
        pass
 
obj1=MyClass()               # 根据MyClass创建对象

  

类中定义的方法,和以前定义函数一样,都是用来实现某种功能的,不过定义方法的时候必须传至少一个参数(self),代表创建的对象,而函数则不需要

class MyClass():
    def func(self,str):
        print(self,str)

obj =  MyClass()  #self是哪个对象调用 self就是那个对象
print(obj)          #<__main__.MyClass object at 0x02786570>

obj.func(‘test‘) #<__main__.MyClass object at 0x02786570>

 

三、面向对象三大特性,封装、继承和多态

1、封装

  从封装本身的意思去理解,封装就好像是拿来一个麻袋,把小猫,小狗,小王八,还有alex一起装进麻袋,然后把麻袋封上口子。照这种逻辑看,封装=‘隐藏’,这种理解是相当片面的。

class A:
    def __init__(self,name):        # 构造函数,初始化数据,
        self.name=name              # 封装数据
 
    def f1(self):
        print(self.name)            # 通过self获取封装的数据
 
a=A(‘jason‘)
a.f1()                              #通过对象获取封装数据

  

在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的形式访问到.

# print(A.__N)  #报错
print(A._A__N)#A._A__N是可以访问到的,
#这种,在外部是无法通过__x这个名字访问到。

 这种变形需要注意的是: 

1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形,主要用来限制外部的直接访问。

2.变形的过程只在类的定义时发生一次,在定义后的赋值操作,不会变形

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

技术分享图片
#把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
View Code

2、继承

继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。

子类会“”遗传”父类的属性,从而解决代码重用问题

class ParentClass1: #定义父类
    pass

class ParentClass2: #定义父类
    pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
    pass

查看继承

>>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
(<class __main__.ParentClass1>,)
>>> SubClass2.__bases__
(<class __main__.ParentClass1>, <class __main__.ParentClass2>)

 

 在开发程序的过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时

我们不可能从头开始写一个类B,这就用到了类的继承的概念。

通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用

技术分享图片
==========================第一部分
例如

  猫可以:喵喵叫、吃、喝、拉、撒

  狗可以:汪汪叫、吃、喝、拉、撒

如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,伪代码如下:
 

#猫和狗有大量相同的内容
class 猫:

    def 喵喵叫(self):
        print 喵喵叫

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something

class 狗:

    def 汪汪叫(self):
        print 喵喵叫

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something



==========================第二部分
上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:

  动物:吃、喝、拉、撒

     猫:喵喵叫(猫继承动物的功能)

     狗:汪汪叫(狗继承动物的功能)

伪代码如下:
class 动物:

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something

# 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class 猫(动物):

    def 喵喵叫(self):
        print 喵喵叫
        
# 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class 狗(动物):

    def 汪汪叫(self):
        print 喵喵叫




==========================第三部分
#继承的代码实现
class Animal:

    def eat(self):
        print("%s 吃 " %self.name)

    def drink(self):
        print ("%s 喝 " %self.name)

    def shit(self):
        print ("%s 拉 " %self.name)

    def pee(self):
        print ("%s 撒 " %self.name)


class Cat(Animal):

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

    def cry(self):
        print(喵喵叫)

class Dog(Animal):

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

    def cry(self):
        print(汪汪叫)


# ######### 执行 #########

c1 = Cat(小白家的小黑猫)
c1.eat()

c2 = Cat(小黑的小白猫)
c2.drink()

d1 = Dog(胖子家的小瘦狗)
d1.eat()

使用继承来重用代码比较好的例子
代码重用示例

3、多态

多态指的是同一种事物的多种状态:水这种事物有多种不同的状态:冰,水蒸气

多态性的概念指出了对象如何通过他们共同的属性和动作来操作及访问,而不需考虑他们具体的类。

冰,水蒸气,都继承于水,它们都有一个同名的方法就是变成云,但是冰.变云(),与水蒸气.变云()是截然不同的过程,虽然调用的方法都一样

class H2o:
    def __init__(self,name,temperature):
        self.name = name
        self.temperature = temperature

    def Water_change(self):
        if self.temperature > 0 and self.temperature < 100:
            print("%s 现在是液态水" %self.name)
        elif self.temperature > 100:
            print("%s 现在是水蒸气" % self.name)
        elif self.temperature < 0:
            print("%s 现在水结冰了" % self.name)

class Water(H2o):
    pass
class Ice(H2o):
    pass
class Steam(H2o):
    pass

w1 = Water(‘水‘,20)

i1 = Ice(‘冰‘,-20)

s1 = Steam(‘水蒸气‘,1000)

def func(obj):
    obj.Water_change()
func(w1) #水 现在是液态水
func(i1) #冰 现在水结冰了
func(s1)#水蒸气 现在是水蒸气

  

 



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

Java中面向对象的三大特性之封装

Scala的面向对象与函数编程

python之路之前没搞明白4面向对象(封装)

JAVA方法的定义

PHP面向对象之选择工厂和更新工厂

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