MATLAB面向对象程序设计——牛顿法求解非线性方程
1. 面向对象程序设计简述
面向过程(Procedure Oriented,简称PO)思想即把求解的问题流程化,把一个复杂的大任务分解为小任务或子过程,子过程可继续划分,进而对子过程进行函数设计、编码实现;或者把一个算法分解为可解决的功能模块,或求解步骤流程化,按照功能模块或步骤进行程序设计。
面向对象(Object Oriented,简称OO)是一种程序设计思想。从20世纪60年代提出面向对象的概念到现在,它已经发展成为一种比较成熟的编程思想,并且逐步成为目前软件开发领域的主流技术。面向对象设计理念是一种从组织结构上模拟客观世界的方法。
面向对象程序设计是在面向过程程序设计的基础上发展而来的,它比面向过程编程具有更强的灵活性、扩展性。面向对象程序设计也是一个程序员发展的“分水岭”,读者应深刻理解面向对象设计的思想。
类(Class)和对象(Object)是面向对象编程(Object Oriented Programming,简称OOP)的核心概念:
“类”是封装对象的属性和行为的载体,它是一个模板,一种抽象的概念,用于描述一类对象的状态(属性、变量及其数据)和行为(方法或函数)。反过来说,具有相同属性和行为的一类实体被称为类。
“对象”是类的一个实例,实例化的对象有状态和行为。一个对象通常被划分为静态部分和动态部分:
静态部分被称为“属性”,任何对象都具备自身的属性,这些属性不仅是客观存在的,而且是不能被忽视的。如平面几何图形的边数
、周长
、面积
等,又如迭代逼近算法的迭代初值
、最大迭代次数
、精度要求
等。
动态部分指的是对象的行为或方法,即对象执行的动作、调用的方法或函数。如平面几何类中根据判断几何图形的类型是圆形、三角形还是四边形,以及计算周长、面积等。
类与对象的关系:类是一类事物的描述,是抽象的。对象是一类事物的实例,是具体的。类是对象的模板,对象是类的实体。类定义了一类对象有哪些属性和方法,但并没有实际的空间,实例化出的对象占有实际空间,用来存储成员变量。
注:算法从某种程度上来说,就是处理计算各种数据,算法可以说就是值的计算和处理。而变量作为数据的存储载体,在算法设计中无处不在,对象在实例化后,本质上就已经传递或存储了类属性数据。
总之,对于一个复杂的问题进行子问题的划分,面向过程把子问题设计为函数,数据在函数间通过参数交互,解决复杂问题;而面向对象,其对应的子问题可以设计为类并实例化为对象,对象拥有属性(数据)和方法(函数),对象之间通过组合和交互来解决问题。
本文基于数值分析与科学计算设计算法,相对于大型软件开发,其面向对象程序设计的思想并不复杂,主要涉及类的定义和设计,以及对象的实例化和调用。
2. MATLAB面向对象程序设计方法
以五种形式的牛顿迭代法求解非线性方程的近似解为例(参考原理),说明MATLAB面向对象的设计流程、方法和思想。
(1)类的定义
关键字classdef 修饰,定义了牛顿迭代法类NewtonRoot(多个单词,每个单词首字母大写,“驼峰式”命名),同时继承handle类,使得能够在类内构造函数外修改属性并可不返回新变量。
(2)类的属性定义
关键字修饰properties,默认为公有属性,通过参数(Access=protected)设置访问权限。
类的属性变量,用于存储数据,便于对象和方法之间数据的传递、共享和计算。对于牛顿迭代法求解非线性方程,其问题本身应该包括待求方程equ_func、初值x0等,除此之外,在各方法间涉及到方程一阶导数和二阶导数的计算。
对于属性定义,说明如下:
属性变量对数据类型没有限制,可以是标量(double, string...)或矩阵(
)等;
属性变量可以有默认值,默认值可以直接赋予一个值,也可以是一个MATLAB表达式(仅在类实例化时计算一次)
常量属性在对象生存周期中保持不变,不能对其进行修改,如重力加速度常数
;
非独立属性的值依赖于其他属性,一旦其他属性的值改变,则该属性也会改变;支持点调用和向量化操作。
属性的访问限制:私有属性private,只有该类的成员方法可以访问该数据,而子类和其他外部函数无法访问;保护属性protected,只有该类的成员方法和子类可以访问该数据;公有属性public,该类的成员方法、子类的成员方法、类之外的函数都可以访问该数据
(3)类的方法定义
关键字methods修饰,默认公有属性,通过参数(Access=protected)设置访问权限。
1)类的构造方法
类的构造方法是对象实例化的第一步操作,负责创建类的对象,初始化对象的属性。构造函数与类名相同,一个类的定义中只能有一个构造函数。如下代码所示,主要包括类属性的初始化、类属性的健壮性检验、必要属性的初始化计算等。
此处类的构造函数的输出参数限制为self,即表示类对象本身。可以使用其他名称,如obj,但在类的整个定义中应统一,本文统一采用self。
2)setXXX和getXXX方法
由于类的属性访问权限的设置,对象不能直接访问类的属性,但可以通过setXXX和getXXX所提供的方法进行访问。主要指通过对象访问类属性(getXXX)和修改类属性值(setXXX),并在修改参数值时进行必要的参数检验和断言。
注意:每个方法的第一个参数限定为self。以供对象点调用。
3)类方法
注意:该方法的输入参数限制为self,以供对象点调用。其他参数是设置可根据实际所解决的问题设置。可以在类定义中仅给出函数的声明,将函数的实现放到一个单独的文件中,但构造函数、析构函数、static(静态)函数除外。
4)类的其他方法
本例中,定了六个保护属性protected的方法,实例化的对象不能直接调用。
3. MATLAB面向对象程序设计完整代码(牛顿迭代法)
4. MATLAB面向对象程序设计——测试调用
具体实例参考牛顿迭代法的面向过程设计
(1)对象的实例化
对象的实例化为OOP的第一步,然后才能通过对象调用其他方法。如下代码所示,实例化后,对象拥有类定义的所有属性变量和方法。必要参数必须传递,可变参数通过关键字参数Name-Value的形式传递(如"display", "iter")。
(2)对象访问类属性
由于类类型定义时,其访问权限为保护属性protected,不允许类外调用,即使是实例化的对象。如显示对象nt_obj,命令行窗口显示如下:
如图1所示,当前实例化的对象尽可访问的属性或方法仅仅是定义为公有属性的方法。

但可以通过类方法所提供的getXXX和setXXX方法访问和修改类属性变量的值。对象访问类方法的方法为“对象名.方法名()”
现修改类属性的访问权限为public,则实例化后,对象可以显示所有属性信息,且对象可以直接访问类的所有属性。通常情况下,类属性定义为私有属性或保护属性。
(3)对象调用方法
由于类方法solve_newton除self外无其他参数,可不传参,此处省略(),若有除self外的参数,则必须传参(args)。
通过调用setmethod(method)修改牛顿法的迭代形式,求解不同情形下的非线性方程的近似解。
(4)完整测试代码,命名文件名为“test_newton_root_object”
输出过程(简化的牛顿法不收敛):
各牛顿法的误差收敛曲线如图2所示,由于简化牛顿法不收敛或收敛较慢,故不再可视化。
