第五章:5.2面向对象-绑定方法和非绑定方法| 内置方法 |元类

5、绑定方法与非绑定方法

在类内部定义的函数,分为两大类:
一:绑定方法:绑定给谁,就应该由谁来调用,谁来调用就会把调用者当作第一个参数自动传入
  绑定到对象的方法:在类内定义的没有被任何装饰器修饰的,会把自己当做第一个参数传进去;

  绑定到类的方法:在类内定义的被装饰器classmethod修饰的方法。

二:非绑定方法:没有自动传值这么一说了,就类中定义的一个普通工具,对象和类都可以使用调用
  非绑定方法:不与类或者对象绑定;

#####绑定到对象
class Foo:
    def __init__(self,name):
        self.name = name
    def tell(self):   #绑定到对象的方法;类内部定义的函数就是给对象使用的
        print('名字是%s'%self.name)
f = Foo('egon')
#print(Foo.tell)  #<function Foo.tell at 0x000000000299CB70>   类访问自己内部函数属性的时候,它就是一个普通函数,没有自动传值一说
#Foo.tell(f)      #名字是egon                                   类非要用,就要给它传值
# print(f.tell)   #<bound method Foo.tell of <__main__.Foo object at 0x00000000027BF630>> 绑定方法指向类的那个函数,跟类使用的是一个功能。  

f.tell()        #名字是egon                                  绑定给谁就由谁来调用,就会把调用者当做第一个参数自动传进去;
#####绑定到类
class Foo:
    def __init__(self,name):
        self.name = name
    def tell(self):
        print('名字是%s'%self.name)
    @classmethod   ###绑定到类的方法
    def func(cls): #绑定到类,把类当做第一个参数传进去;cls=Foo
        print(cls)

print(Foo.func) #<bound method Foo.func of <class '__main__.Foo'>>  加了装饰器后,定义成绑定到类的方法而不是函数了
Foo.func()      #<class '__main__.Foo'>
######非绑定方法,没有自动传值了
class Foo:
    def __init__(self,name):
        self.name = name
    def tell(self):
        print('名字是%s'%self.name)
    @classmethod
    def func(cls): #绑定到类,把类当做第一个参数传进去;
        print(cls)
    @staticmethod  #这才被认为一个真正意义上的函数,没有自动传值了。非绑定方法加个@staticmethod
    def func1(x,y):
        print(x+y)

f = Foo('egon')
f.func()         #<class '__main__.Foo'>
print(Foo.func1) #<function Foo.func1 at 0x000000000296CC80>  类 都是普通函数
print(f.func1)   #<function Foo.func1 at 0x000000000296CC80>  对象 普通函数

Foo.func1(1,2)  #3  类来调用
f.func1(2,4)    #6  对象来调用

在类内部定义的函数分为两大类:绑定方法和非绑定方法(就是普通函数)。

使用场景

根据函数体的逻辑想传什么参数

class People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def tell_info(self): #绑定到对象的方法
        print('Name:%s Age:%s Sex:%s'%(self.name,self.age,self.sex))
p = People('egon',18,'male')
#绑定给对象,就应该由对象来调用,自动将对象本身当做第一个参数传入
p.tell_info() #tell_info(p) # Name:egon Age:18 Sex:male
import settings  #写一个配置文件  name = 'alex'  age = 18  sex = male
class People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def tell_info(self): #绑定到对象的方法
        print('Name:%s Age:%s Sex:%s'%(self.name,self.age,self.sex))
    @classmethod
    def from_conf(cls):   #不能写死,需要写个参数把类传进去
        obj = cls(
            settings.name,
            settings.age,
            settings.sex
        )
        return obj
#绑定给类,就应该由类来调用,自动将类本身当做第一个参数传入
p = People.from_conf() #本质上就是from_conf(People)  #从配置文件里边读取配置进行实例化
p.tell_info()         #Name:alex Age:18 Sex:male
import settings
import hashlib
import time
class People:
    def __init__(self,name,age,sex):
        self.id = self.creat_id()  #需要传参数就传
        self.name = name
        self.age = age
        self.sex = sex
    def tell_info(self): #绑定到对象的方法
        print('Name:%s Age:%s Sex:%s'%(self.name,self.age,self.sex))
    @classmethod
    def from_conf(cls):
        obj = cls(
            settings.name,
            settings.age,
            settings.sex
        )
        return obj
#非绑定方法,不与类或者对象绑定,谁都可以调用,没有自动传值一说
    @staticmethod
    def creat_id():  #不依赖类和对象传入参数
        m=hashlib.md5(str(time.time()).encode('utf-8'))
        return m.hexdigest()
p1=People('egon1',18,'male')
p2=People('egon2',28,'male')
p3=People('egon3',38,'male')
print(p1.create_id()) #66c0399486670e0faaab1324e98b33b0
print(p2.id)          #66c0399486670e0faaab1324e98b33b0
print(p3.id)          #66c0399486670e0faaab1324e98b33b0

6、反射

通过字符串来映射到一个对象的属性

class People:
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def talk(self):
        print('%s is talking' %self.name)
obj=People('egon',18)
# print(obj.name)   #obj.__dict__['name'] #.后面是个属性,而不是字符串;用户通过字符串来映射到一个对象的属性身上
# print(obj.talk)   #<bound method People.talk of <__main__.People object at 0x00000000027DFB00>>
# choice=input('>>: ') #choice='name'
# print(obj.choice) #会报错 print(obj.'name')

#判断有没有这个属性
print(hasattr(obj,'name'))  #True  obj.name #obj.__dict__['name']
print(hasattr(obj,'talk'))  #True  obj.talk
#拿到对象的属性 ,没有就报错
print(getattr(obj,'name'))        # egon
print(getattr(obj,'namexx',None)) # None
print(gatattr(obj,'talk')) #<bound method People.talk of <__main__.People object at 0x0000000002961F28>>
#修改 或新增 setattr(obj,'sex','male') #obj.sex = 'male' print(obj.sex) # male #删除 delattr(obj,'age') # del obj.age print(obj.__dict__) # {'name': 'egon', 'sex': 'male'} #类同样适用以上方法 print(getattr(People,'country')) #People.country #China
####反射的应用:
class Service:
    def run(self):
        while True:
            inp=input('>>: ').strip() #cmd='get a.txt'
            cmds=inp.split() #cmds=['get','a.txt']
            # print(cmds)
            if hasattr(self,cmds[0]): #判断有没有get这个方法
                func=getattr(self,cmds[0]) #拿到它
                func(cmds)  #执行
    def get(self,cmds):
        print('get.......',cmds)
    def put(self,cmds):
        print('put.......',cmds)
obj=Service()
obj.run()

7、内置方法

http://www.cnblogs.com/linhaifeng/articles/6204014.html

isinstance(obj,cls)检查是否obj是否是类 cls 的对象,判断谁是谁的实例;

issubclass(sub, super)检查sub类是否是 super 类的派生类

只要是__开头__结尾的方法都不要直接去用,python会自动调用的,什么情况下会触发呢?

####item系列 #把对象模拟成像字典样
###获取
class Foo: #Dict
    def __init__(self,name):
        self.name=name
    def __getitem__(self, item): #要知道item获取的什么值 #item='name',把name传进去;我通过字符串怎么访问属性呢,可以用反射,也可以self.__dict__(item)
        print('getitem...')
        print(item)
        return self.__dict__.get(item) #这样就取到值了;通过字典的key取它的value  ##有就取值,没有就不会报错了
    def __setitem__(self, key, value):
        print('setitem...')
        print(key,value)
        self.__dict__[key]=value
    def __delitem__(self, key):
        print('delitem...')
        print(key)
        del self.__dict__[key]
obj=Foo('egon')      ##把obj模拟成字典的样子
print(obj.__dict__)  #{'name': 'egon'}
###查看属性
#obj.属性名 #原来是这样获取的
#obj['name']          #打印出:getitem...  name        obj.name想要完成这样一个取值,应该让那个方法有个返回值;按照这种形式一打开它就会触发__getitem__来取值
#print(obj['name']    #打印出:getitem...  name    egon
print(obj['namexx'])  #打印出:getitem...  namexx  None    obj.name
class Foo: #Dict
    def __init__(self,name):
        self.name=name
    def __getitem__(self, item): #要知道item获取的什么值 #item='name'
        print('getitem...')
        print(item)
        return self.__dict__.get(item) #通过字典的key取它的value #有就取值,没有就不会报错了
    def __setitem__(self, key, value): #value就是要设置的值
        #print('setitem...')
        #print(key,value)
        self.__dict__[key]=value  #这样就完成了真正的设置,上边两步就可以去掉了
    def __delitem__(self, key):
        print('delitem...')
        print(key)
        del self.__dict__[key]
obj=Foo('egon')
#print(obj.__dict__)

#设置属性
#obj.sex = 'male' 
obj['sex'] = 'male' #会触发__setitem__,并且打印key,value
print(obj.__dict__) #验证下,设置成功了  #{'name': 'egon', 'sex': 'male'}
print(obj.sex)      #获取 male
class Foo: #Dict
    def __init__(self,name):
        self.name=name
    def __getitem__(self, item): #要知道item获取的什么值 #item='name'
        #print('getitem...')
        #print(item)
        return self.__dict__.get(item) #通过字典的key取它的value #有就取值,没有就不会报错了
    def __setitem__(self, key, value):
        #print('setitem...')
        #print(key,value)
        self.__dict__[key]=value  #这样就完成了真正的设置,上边两步就可以去掉了
    def __delitem__(self, key):
        #print('delitem...')
        #print(key)
        del self.__dict__[key]  ##完成真正的删除
obj=Foo('egon')
#print(obj.__dict__)
#查看属性
#obj.属性名 #原来是这样获取的
#obj['name'] #obj.name 想要完成这样一个取值,应该让那个方法有个返回值;一打开它就会触发__getitem__来取值
#print(obj['namexx'])  #obj.name

#设置属性
#obj.sex = 'male'
# obj['sex'] = 'male' #会触发__setitem__,并且打印key,value
# print(obj.__dict__) #验证下,设置成功了
# print(obj.sex) #获取

#删除属性
#del obj.name
del obj['name']
print(obj.__dict__)  #delitem...  name  {}
#########__str__方法: 
# d=dict({'name':'egon'})
# print(isinstance(d,dict)) #True
# print(d)                 #{'name','egon'} #打印成有用的东西,而不是打印成内存地址

class People:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __str__(self):  #__str__定义完之后,会在打印对象的时候会触发对象下的__str__方法,然后把返回字符串类型的结果打印出
        print('====>str')
        return '<name:%s,age:%s>' %(self.name,self.age)  #要返回一个字符串类型
obj=People('egon',18)
print(obj) #打印出:====>str  <name:egon,age:18>   ;res=obj.__str__()  #一打印的时候就会触发 obj.__str__()这个方法,把它的结果拿到打印
####__del__  回收资源的
# f=open('settings.py')
# f.read()
# f.close() #回收操作系统的资源 ,执行它后f这个变量还存在

# print(f)  #<_io.TextIOWrapper name='settings.py' mode='r' encoding='cp936'>
# f.read()

class Open:
    def __init__(self,filename):
        print('open file.......') #给操作系统发一个请求
        self.filename=filename
    def __del__(self):   ##在对象被删除的时候会先触发这个方法的执行再删除。 程序运行完之后py会自动给你删对象,在删对象之前先触发这个方法的执行;
    print('回收操作系统资源:self.close()')  #py只会帮你回收对象本身,并不会给你回收对象相关的属性,这时候就可以写在这里了使用__del__
f=Open('settings.py') #它是一个变量,占应用程序的一个内存 
#del f #del f 如果运行这一步是程序先运行打开文件,然后回收操作系统资源,最后执行完程序。 #同样也会触发它 f.__del__() 
print('----main------') ##代表程序执行完了会自动触发del f的执行; 但遗留下操作系统的资源。

 8、元类介绍

exec:三个参数

参数一:字符串形式的命令

参数二:全局作用域(字典形式),如果不指定,默认为globals()

参数三:局部作用域(字典形式),如果不指定,默认为locals()
g={
    'x':1,
    'y':2
}
l={}
#可以把exec看做一个函数,g,l是指定全局和局部作用域
exec("""
global x,m
x=10
m=100
z=3
""",g,l)
print(g)
print(l)

一切皆对象,对象可以怎么用?
1、都可以被引用,x=obj
2、都可以当作函数的参数传入
3、都可以当作函数的返回值
4、都可以当作容器类的元素,l=[func,time,obj,1]

##类也是对象,Foo=type(....) 看做type传了个值进去
class Foo:
    pass
obj=Foo()
print(type(obj)) #<class '__main__.Foo'>
print(type(Foo)) #<class 'type'>

class Bar:
    pass
print(type(Bar)) #查看类型 #<class 'type'>
##产生类的类称之为元类,默认所以用class定义的类,他们的元类是type

  元类是类的类,是类的模板

元类是用来控制如何创建类的,正如类是创建对象的模板一样,而元类的主要目的是为了控制类的创建行为

元类的实例化的结果为我们用class定义的类,正如类的实例为对象(f1对象是Foo类的一个实例,Foo类是 type 类的一个实例)

type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象.

定义类的两种方式:

#定义类的两种方式:
#方式一:使用class关键字
class Chinese: #Chinese=type(...)
    country='China'
    def __init__(self,namem,age):
        self.name=namem
        self.age=age
    def talk(self):
        print('%s is talking' %self.name)
# print(Chinese)
obj=Chinese('egon',18)
print(obj,obj.name,obj.age)


#方式二:type  手动模拟class创建类的过程,将创建类的步骤拆分开,手动去创建。
#定义类的三要素:类名,类的基类们,类的名称空间
class_name='Chinese' #类名
class_bases=(object,) #继承的基类;类的父类
class_body="""       #类体
country='China'
def __init__(self,namem,age):
    self.name=namem
    self.age=age
def talk(self):
    print('%s is talking' %self.name)
""" 
class_dic={} #放到字典里初始化为空      #应该把上边"""  """里边类体的代码执行一下得到的结果放到一个字典里边;
exec(class_body,globals(),class_dic) 
# print(class_dic)  #{'country': 'China', '__init__': <function __init__ at 0x00000000003D3E18>, 'talk': <function talk at 0x0000000001F1CAE8>}

Chinese1=type(class_name,class_bases,class_dic) #得到一个元类 # print(Chinese1) #<class '__main__.Chinese'> obj1=Chinese1('egon',18) print(obj1,obj1.name,obj1.age) #<__main__.Chinese object at 0x00000000029619B0> egon 18

步骤一(先处理类体->名称空间):类体定义的名字都会存放于类的名称空间中(一个局部的名称空间),我们可以事先定义一个空字典,然后用exec去执行类体的代码(exec产生名称空间的过程与真正的class过程类似,只是后者会将__开头的属性变形),生成类的局部名称空间,即填充字典

步骤二:调用元类type(也可以自定义)来产生类Chinense 

我们看到,type 接收三个参数:

  • 第 1 个参数是字符串 ‘Foo’,表示类名
  • 第 2 个参数是元组 (object, ),表示所有的父类
  • 第 3 个参数是字典,这里是一个空字典,表示没有定义属性和方法

补充:若Foo类有继承,即class Foo(Bar):.... 则等同于type('Foo',(Bar,),{})

自定义元类控制类的创建

#一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类(顺便我们也可以瞅一瞅元类如何控制类的行为,工作流程是什么)
#自定义元类控制类的行为
class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):  #可能覆盖父类;继承默认元类的一堆属性
        if not class_name.istitle():
            raise TypeError('类名的首字母必须大写') #会报错
        print(class_dic)  #{'__module__': '__main__', '__qualname__': 'Chinese', '__doc__': 'a
    中文人的类  ##注释写上之后才有__doc__属性
    ', 'country': 'China', '__init__': <function Chinese.__init__ at 0x000000000296CB70>, 'talk': <function Chinese.talk at 0x000000000296CBF8>}
        if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
            raise TypeError('必须有注释,且注释不能为空')
        super(Mymeta,self).__init__(class_name,class_bases,class_dic)  #你写__init__这个功能之前把父类的也重用了一遍
class Chinese(object,metaclass=Mymeta):  #指定元类为Mymeta,这个类Chinese的创建行为就由你来控制了
    '''a
    中文人的类  ##注释写上之后才有__doc__属性
    '''
    country='China'
    def __init__(self,namem,age):
        self.name=namem
        self.age=age
    def talk(self):
        print('%s is talking' %self.name)
# Chinese=Mymeta(class_name,class_bases,class_dic)  #在实例化,必须要有个__init__方法;触发Mymeta实例化的过程就会触发__init__方法的执行

自定义元类控制类的实例化

#知识储备__call__方法 #让对象变成可调用对象  
class Foo:
    def __call__(self, *args, **kwargs):
        print(self)   #<__main__.Foo object at 0x0000000001DBB128>
        print(args)   #(1, 2, 3)
        print(kwargs) #{'a': 1, 'b': 2, 'c': 3}
obj=Foo()  #obj之所以可以调用是因Foo里边有个__call__方法
obj(1,2,3,a=1,b=2,c=3) #obj.__call__(obj,1,2,3,a=1,b=2,c=3)
# #元类内部也应有有一个__call__方法,会在调用Foo时触发该方法的执行
# #Foo(1,2,x=1)  #Foo.__call__(Foo,1,2,x=1)
class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        if not class_name.istitle():
            raise TypeError('类名的首字母必须大写')
        if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
            raise TypeError('必须有注释,且注释不能为空')
        super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    def __call__(self, *args, **kwargs): #obj=Chinese('egon',age=18) #一个类实例化的行为就是__call__里边的内容
        # print(self) #self=Chinese
        # print(args) #args=('egon',)
        # print(kwargs) #kwargs={'age': 18}
        #之前学的是调用Chinese所要做的三件事情:  ##这其实就是__call__方法内部
        #第一件事:先造一个空对象obj
        obj=object.__new__(self)  #self= Chinese
        #第二件事:初始化obj
        self.__init__(obj,*args,**kwargs) #把空对象传进来,把参数传进来
        #第三件事:返回obj
        return obj
class Chinese(object,metaclass=Mymeta):
    '''
    中文人的类
    '''
    country='China'
    def __init__(self,namem,age):
        self.name=namem
        self.age=age
    def talk(self):
        print('%s is talking' %self.name)
obj=Chinese('egon',age=18) #Chinese.__call__(Chinese,'egon',18) 调用这个对象会触发它的类Mymeta,下面那个__call__

print(obj.__dict__)  #{'name': 'egon', 'age': 18}

应用

#单例模式 对象内部特征是一样的话就不要产生空间,用一个空间就可以了,节省空间
#实现方式一:
class MySQL:
    __instance=None #__instance=obj1
    def __init__(self):
        self.host='127.0.0.1'
        self.port=3306
    @classmethod
    def singleton(cls):
        if not cls.__instance:
            obj=cls()
            cls.__instance=obj
        return cls.__instance
    def conn(self):
        pass
    def execute(self):
        pass
# obj1=MySQL()
# obj2=MySQL()
# obj3=MySQL()
# print(obj1)
# print(obj2)
# print(obj3)
obj1=MySQL.singleton()
obj2=MySQL.singleton()
obj3=MySQL.singleton()
print(obj1 is obj3)
#实现方式二:元类的方式
class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        if not class_name.istitle():
            raise TypeError('类名的首字母必须大写')
        if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
            raise TypeError('必须有注释,且注释不能为空')
        super(Mymeta,self).__init__(class_name,class_bases,class_dic)
        self.__instance=None  #设置个属性
    def __call__(self, *args, **kwargs): #obj=Chinese('egon',age=18)
        if not self.__instance:  #没有__instance就给它造一个
            obj=object.__new__(self) #造一个空对象
            self.__init__(obj)  #self代表Mysql
            self.__instance=obj
        return self.__instance  #有就返回
class Mysql(object,metaclass=Mymeta):
    '''
    Mysql xxx
    '''
    def __init__(self):
        self.host='127.0.0.1'
        self.port=3306
    def conn(self):
        pass
    def execute(self):
        pass
obj1=Mysql()  #调用这个对象触发__call__下面的方法
obj2=Mysql()
obj3=Mysql()
print(obj1 is obj2 is obj3)

python中的__init__、__new__方法

class TestCls():
    """docstring for TestCls"""

    def __init__(self, name):
        print('init')
        print(self)
        print(type(self))
        self.name = name

    def __new__(cls, name):
        print('new')
        print(cls)
        print(type(cls))
        return super().__new__(cls)

c = TestCls("CooMark")

# new...
# <class '__main__.TestCls'>
# <class 'type'>

# init...
# <__main__.TestCls object at 0x02201130>
# <class '__main__.TestCls'>

异同点


  1. 参数
    • __new__的第一个占位参数是class对象
    • __init__的第一个占位参数是class的实例对象
    • 其他的参数应一致
  2. 作用
    • __new__ 用来创建实例,在返回的实例上执行__init__,如果不返回实例那么__init__将不会执行
    • __init__ 用来初始化实例,设置属性什么的

__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass

  • 继承不可变class 

假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码

class PositiveInteger(int):

    def __init__(self, value):
        super().__init__(self, abs(value))

i = PositiveInteger(-3)
print(i)
# # TypeError: object.__init__() takes no parameters


class PositiveInteger(int):

    def __new__(cls, value):
        return super(PositiveInteger, cls).__new__(cls, abs(value))
i = PositiveInteger(-3)
print(i)
# 3
  • 用__new__来实现单例
class Singleton(object):
    def __new__(cls):
        # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance
obj1 = Singleton()
obj2 = Singleton()
obj1.attr1 = 'value1'
print( obj1.attr1, obj2.attr1)
print( obj1 is obj2)

参考:http://www.jb51.net/article/48044.htm

__new__: 对象的创建,是一个静态方法,第一个参数是cls。(想想也是,不可能是self,对象还没创建,哪来的self)

__init__ : 对象的初始化, 是一个实例方法,第一个参数是self。

__call__ : 对象可call,注意不是类,是对象。

先有创建,才有初始化。即先__new__,而后__init__。

    __call__方法  对象可call,注意不是类,是对象。

     当实现了这个方法时,这个类的实例(对象)可以当作函数一样调用。
  比如类A实现了__call__(self, x), 那么
  a = A()
  a(x) #把a当函数使

面向对象的软件开发 

面向对象的软件工程包括下面几个部:

1.面向对象分析(object oriented analysis ,OOA)

软件工程中的系统分析阶段,要求分析员和用户结合在一起,对用户的需求做出精确的分析和明确的表述,从大的方面解析软件系统应该做什么,而不是怎么去做。面向对象的分析要按照面向对象的概念和方法,在对任务的分析中,从客观存在的事物和事物之间的关系,归纳出有关的对象(对象的‘特征’和‘技能’)以及对象之间的联系,并将具有相同属性和行为的对象用一个类class来标识。

建立一个能反映这是工作情况的需求模型,此时的模型是粗略的。

2 面向对象设计(object oriented design,OOD)

根据面向对象分析阶段形成的需求模型,对每一部分分别进行具体的设计。

首先是类的设计,类的设计可能包含多个层次(利用继承与派生机制)。然后以这些类为基础提出程序设计的思路和方法,包括对算法的设计。

在设计阶段并不牵涉任何一门具体的计算机语言,而是用一种更通用的描述工具(如伪代码或流程图)来描述

3 面向对象编程(object oriented programming,OOP)

根据面向对象设计的结果,选择一种计算机语言把它写成程序,可以是python

4 面向对象测试(object oriented test,OOT)

在写好程序后交给用户使用前,必须对程序进行严格的测试,测试的目的是发现程序中的错误并修正它。

面向对的测试是用面向对象的方法进行测试,以类作为测试的基本单元。

5 面向对象维护(object oriendted soft maintenance,OOSM)

正如对任何产品都需要进行售后服务和维护一样,软件在使用时也会出现一些问题,或者软件商想改进软件的性能,这就需要修改程序。

由于使用了面向对象的方法开发程序,使用程序的维护比较容易。

因为对象的封装性,修改一个对象对其他的对象影响很小,利用面向对象的方法维护程序,大大提高了软件维护的效率,可扩展性高。

在面向对象方法中,最早发展的肯定是面向对象编程(OOP),那时OOA和OOD都还没有发展起来,因此程序设计者为了写出面向对象的程序,还必须深入到分析和设计领域,尤其是设计领域,那时的OOP实际上包含了现在的OOD和OOP两个阶段,这对程序设计者要求比较高,许多人感到很难掌握。

现在设计一个大的软件,是严格按照面向对象软件工程的5个阶段进行的,这个5个阶段的工作不是由一个人从头到尾完成的,而是由不同的人分别完成,这样OOP阶段的任务就比较简单了。程序编写者只需要根据OOd提出的思路,用面向对象语言编写出程序既可。

原文地址:https://www.cnblogs.com/shengyang17/p/9196995.html