软件构造第三章4

第3章:抽象数据类型(ADT)和面向对象编程(OOP)3.4面向对象编程(OOP)
3.4面向对象编程(OOP)
大纲
1.面向对象的标准2.基本概念:对象,类,属性,方法和接口3. OOP的不同特征封装和信息隐藏继承和覆盖多态性,子类型和重载静态和动态调度组合和委托4. Java中的一些重要的Object方法5.编写不可变的类6. OOP的历史7.总结
3.4面向对象编程(OOP)
本讲座的目的
将抽象数据类型的接口与其实现分离,并使用Java接口类型强制执行该分离。 使用接口定义ADT,并编写实现接口的类。
软件构建
1面向对象的标准
3.4面向对象编程(OOP)面向对象标准
OO编程方法/语言应该以类的概念作为核心概念。 语言应该可以为类及其功能配备断言(前置条件,后置条件和不变量)和异常处理,依靠工具从这些断言中生成文档,并可选择在运行时监视它们。 ADT - 他们帮助生产可靠的软件; - 他们提供系统的文件; - 它们是测试和调试面向对象软件的核心工具。 静态类型:定义良好的类型系统应该通过强制执行许多类型声明和兼容性规则来保证它接受的系统的运行时类型安全性。
3.4面向对象编程(OOP)
面向对象的标准
“准备好改变”和“为重用设计”的通用性:应该可以使用表示任意类型的正式通用参数来编写类。 继承:应该可以将类定义为从另一个继承,以控制产生的潜在复杂性。 多态性:应该可以在基于继承的类型系统的控制下,将实体(表示运行时对象的软件文本中的名称)附加到各种可能类型的运行时对象。 动态调度/绑定:调用实体上的功能应始终触发与附加的运行时对象的类型相对应的功能,在不同的调用执行中不一定相同。
软件构建
2基本概念:对象,类,属性和方法
3.4面向对象编程(OOP)
宾语
真实世界的对象共享两个特征:它们都具有状态和行为。识别真实世界对象的状态和行为是开始思考面向对象编程的好方法。 - 狗有状态(名称,颜色,品种,饥饿)和行为(吠叫,取出,摇尾)。 - 自行车还具有状态(当前档位,当前踏板节奏,当前速度)和行为(换档,改变踏板节奏,应用制动)。 对于你看到的每个对象,问自己两个问题,这些现实世界的观察都转化为面向对象编程的世界。 - 这个对象可以包含哪些可能的状态? - 此对象可以执行哪些行为?
3.4面向对象编程(OOP)
宾语
对象是一组状态和行为状态 - 对象中包含的数据。 - 在Java中,这些是对象的字段行为 - 对象支持的操作 - 在Java中,这些被称为方法 - 方法只是OO代表函数 - 调用方法=调用函数
3.4面向对象编程(OOP)

每个对象都有一个类 - 一个类定义方法和字段 - 方法和字段统称为成员类定义类型和实现 - 类型≈可以使用对象 - 实现≈对象如何做事松散地说,类的方法是它的应用程序编程接口(API) - 定义用户与实例的交互方式
3.4面向对象编程(OOP)类示例 - 复数
3.4面向对象编程(OOP)
类用法示例
运行此程序时,它打印什么?静态与实例变量/类的方法
类变量:与类关联的变量,而不是与类的实例关联的变量。您还可以将方法与类 - 类方法相关联。 - 要引用类变量和方法,可以加入类的名称以及类方法或类变量的名称以及句点(’。’)。 非类方法或类变量的方法和变量称为实例方法和实例变量。 - 要引用实例方法和变量,必须从类的实例引用方法和变量。
摘要: - 类变量和类方法与类相关联,每个类发生一次。使用它们不需要创建对象。 - 每个类的实例都会出现一次实例方法和变量。
3.4面向对象编程(OOP)静态与实例变量/类的方法
class DateApp {public static void main(String args []){Date today = new Date();的System.out.println(今天); }}
class Another {public static void main(String [] args){int result; result = Math.min(10,20);的System.out.println(结果); System.out.println(Math.max(100,200)); }}
3.4面向对象编程(OOP)静态与实例变量/类的方法
静态方法不与类的任何特定实例相关联,而实例方法(在没有static关键字的情况下声明)必须在特定对象上调用。
class Difference {
public static void main(String [] args){display(); //无对象调用差异t = new Difference(); t.show(); //使用object调用}
static void display(){System.out.println(“Programming is amazing。”); }
void show(){System.out.println(“Java很棒。”); }
}
3.4面向对象编程(OOP)
公共类MyStatic {
私有字符串名称; private static String staticStr =“STATIC-STRING”;
public MyStatic(String n){this.name = n; }
public static void testStaticMethod(){System.out.println(“嘿…我在静态方法…”); //你可以在这里调用静态变量System.out.println(MyStaticMethods.staticStr); //你不能在这里调用实例变量。 }
public void testObjectMethod(){System.out.println(“Hey i am in non-static method”); //你也可以在这里调用静态变量System.out.println(MyStaticMethods.staticStr); //你可以在这里调用实例变量System.out.println(“Name:”+ this.name); }
public staticvoid main(String a []){//通过使用类名,可以调用静态方法MyStatic.testStaticMethod(); MyStatic msm = new MyStatic(“Java2novice”); msm.testObjectMethod(); }
}
软件构建
3接口
3.4面向对象编程(OOP)
接口
Java的接口是设计和表达ADT的有用语言机制,其实现是实现该接口的类。 - Java中的接口是方法签名列表,但没有方法体。 - 如果一个类在其implements子句中声明了接口,则它实现一个接口,并为所有接口的方法提供方法体。 - 接口可以扩展一个或多个其他接口 - 一个类可以实现多个接口
3.4面向对象的编程(OOP)接口和实现
API的多个实现可以共存 - 多个类可以实现相同的API - 它们可以在性能和行为上有所不同在Java中,API由接口或类指定 - 接口仅提供API - 接口定义但不实现API - Class提供API和实现–Alass可以实现多个接口
3.4面向对象编程(OOP)与示例类一起使用的接口
3.4面向对象编程(OOP)修改类以使用接口
3.4面向对象编程(OOP)修改客户端使用接口
3.4面向对象编程(OOP)接口允许多种实现
3.4面向对象的编程(OOP)接口将客户端与实现分离
3.4面向对象编程(OOP)
Java接口和类
接口与类 - 接口:指定期望 - 类:提供期望(实现)类定义类型 - 可用于接口方法的公共类方法 - 可直接从其他类访问的公共字段但更喜欢使用接口 - 使用变量和参数的接口类型,除非您知道一个实现就足够了。 - 支持改变实施; - 防止依赖实现细节另一个接口示例:MyString
3.4 MyString的面向对象编程(OOP)实现1
3.4 MyString的面向对象编程(OOP)实现2
3.4面向对象的编程(OOP)使用MyString及其实现
问题:打破抽象障碍 - 客户端必须知道具体表示类的名称。 - 因为Java中的接口不能包含构造函数,所以它们必须直接调用其中一个具体类的构造函数。 - 该构造函数的规范不会出现在接口的任何地方,因此没有静态保证不同的实现甚至会提供相同的构造函数。
3.4面向对象编程(OOP)使用静态工厂而不是构造函数
3.4面向对象编程(OOP)
界面的优点
接口指定客户的合同,仅此而已。 - 界面是客户程序员需要阅读以了解ADT的全部内容。 - 客户端无法在ADT的代表上创建无意的依赖关系,因为实例变量根本无法放入接口。 - 实施保持良好且真正分开,完全不同。 抽象数据类型的多个不同表示可以在同一个程序中共存,就像实现接口的不同类一样。 - 当抽象数据类型表示为单个类而没有接口时,很难有多个表示。
3.4面向对象的编程(OOP)为什么要多次实现?
不同的性能 - 选择最适合您使用的实现不同的行为 - 选择实现您想要的实现 - 行为必须符合接口规范(“合同”)性能和行为通常都有所不同 - 提供功能 - 性能权衡 - 示例:HashSet,TreeSet
3.4面向对象编程(OOP)
接口摘要
编译器和人类的文档允许性能权衡可选方法具有故意不确定规范的方法一个类的多个视图越来越不值得信赖的实现
软件构建
4封装和信息隐藏
3.4面向对象编程(OOP)
信息隐藏
将设计良好的模块与坏模块区分开来的唯一最重要的因素是它隐藏内部数据的程度以及其他模块的其他实现细节设计良好的代码隐藏了所有实现细节 - 将API与实现完全分开 - 模块通信只有通过API - 无视彼此的内部工作被称为信息隐藏或封装,是软件设计的基本原则。
3.4面向对象编程(OOP)
信息隐藏的好处
解耦构成系统的类 - 允许它们单独开发,测试,优化,使用,理解和修改加速系统开发 - 可以并行开发类减轻维护负担 - 可以更多地理解类快速调试,无需担心损害其他模块实现有效的性能调优 - “热”类可以独立优化增加软件重用 - 松散耦合的类通常在其他环境中很有用
3.4面向对象编程(OOP)通过接口隐藏信息
使用接口类型声明变量客户端只能使用接口方法客户端代码无法访问的字段但这只需要我们到目前为止 - 客户端可以直接访问非接口成员 - 本质上,它是自愿信息隐藏
3.4面向对象编程(OOP)成员的可见性修饰符
私人 - 只能从声明类访问受保护 - 可以从声明类(和包内)的子类访问公共 - 可从任何地方访问
3.4面向对象编程(OOP)信息隐藏的最佳实践
仔细设计您的API仅提供客户所需的功能,并且其他所有成员应该是私人的您可以随时将私人会员公开,而不会破坏客户 - 但反之亦然!5继承和覆盖
3.4面向对象编程(OOP)
继承和子类型
继承代码重用 - 只编写一次代码 - 子类中隐式可用的超类特性子类型用于多态 - 以相同的方式访问对象,但获得不同的行为 - 子类型可替代超类型
接口定义客户的期望/承诺一个类满足接口的期望 - 抽象类是一个方便的混合 - 一个子类专门化一个类的实现
A类延伸B
A类实现了我
软件构建
(1)压倒一切
3.4面向对象编程(OOP)可重写方法和严格继承
可重写方法:允许重新实现的方法。 - 在Java中,默认情况下方法是可重写的,即没有特殊的关键字。 严格继承 - 子类只能向超类添加新方法,它不能覆盖它们 - 如果某个方法无法在Java程序中覆盖,则必须以关键字final作为前缀。
3.4面向对象编程(OOP)
严格的继承
drive()brake()acceleration()
汽车
playMusic()ejectCD()resumeMusic()pauseMusic()
豪华车
public class LuxuryCar extends Car {public void playMusic(){…} public void ejectCD(){…} public void resumeMusic(){…} public void pauseMusic(){…}}
public class Car {public final void drive(){…} public final void brake(){…} public final void accelerate(){…}}超类
子类
3.4面向对象的编程(OOP)严格的继承和可重写的方法
class Device {int serialnr; public final void help(){…} public void setSerialNr(int n){serialnr = n; }}
class Valve扩展Device {Position s; public void on(){… }}
help()不可覆盖
setSerialNr()可覆盖
3.4面向对象编程(OOP)
Overriding(覆盖/重写)
方法覆盖是一种语言功能,它允许子类或子类提供已由其某个超类或父类提供的方法的特定实现。 - 子类中的实现通过提供与父类中的方法具有相同名称,相同参数或签名以及相同返回类型的方法来覆盖(替换)超类中的实现。 - 执行的方法版本将由用于调用它的对象确定。 - 如果父类的对象用于调用该方法,则将执行父类中的版本,但如果使用子类的对象来调用该方法,则将执行子类中的版本。
3.4面向对象编程(OOP)示例:覆盖方法
class Device {int serialnr; public final void help(){…} public void setSerialNr(int n){serialnr = n; Valve扩展Device {Position s;} public void on(){… }}
class Device {int serialnr; public final void help(){…} public void setSerialNr(int n){serialnr = n; }}
class Valve扩展Device {Position s; public void on(){…} public void setSerialNr(int n){serialnr = n + s.serialnr; }}
3.4面向对象编程(OOP)可重写方法设置为空
class Device {int serialnr; public void setSerialNr(int n){}}类Valve扩展Device {Position s; public void on(){… …} public void setSerialNr(int n){seriennr = n + s.serialnr; } //类Valve
我希望方法setSerialNr()将被覆盖。我只写一个空体
覆盖Class Device的setSerialNr()方法
3.4面向对象编程(OOP)
Overriding(覆盖/重写)
当子类包含覆盖超类方法的方法时,它也可以使用关键字super调用超类方法。
3.4面向对象编程(OOP)
超级扩展重用
3.4面向对象编程(OOP)具有this和super的构造函数
3.4面向对象编程(OOP)错误使用覆盖方法
可以用全新的含义覆盖超类的操作。 示例:
公共类SuperClass {public int add(int a,int b){return a + b; public int subtract(int a,int b){return a-b;公共类SubClass扩展了SuperClass {public int add(int a,int b){return a-b; public int subtract(int a,int b){return a + b;我们已经重新定义了加法作为加法减法和减法!!
3.4面向对象编程(OOP)
最后
最后一个字段:防止在初始化后重新分配到字段最后一个方法:防止覆盖方法最后一个类:阻止扩展类 - 例如,公共最终类CheckingAccountImpl {…(2)抽象类
3.4面向对象的编程(OOP)抽象方法和抽象类
抽象方法: - 具有签名但没有实现的方法(也称为抽象操作) - 由关键字abstract定义抽象类: - 包含至少一个抽象方法的类称为抽象类接口:抽象类它只有抽象方法 - 接口主要用于系统或子系统的规范。实现由子类或其他机制提供。
具体类抽象类接口
软件构建
6多态性,子类型和重载
软件构建
(1)三种多态性
3.4面向对象程序设计(OOP)三种多态(多态)
多态类型是可以将其操作应用于某些其他类型的值的类型。 - Ad hoc多态性:当函数表示不同且可能异构的实现时,取决于单独指定的类型和组合的有限范围。使用函数重载在许多语言中支持Ad hoc多态性。 - 参数多态:当编写代码时不提及任何特定类型,因此可以透明地使用任意数量的新类型。在面向对象的编程社区中,这通常被称为泛型或泛型编程。 - 子类型(也称为子类型多态性或包含多态性):当名称表示由某些常见超类相关的许多不同类的实例时。 (我们已在上一节讨论过)
软件构建
(2)Ad hoc多态和重载
3.4面向对象编程(OOP)
Ad hoc多态性
当函数在几种不同类型(可能不具有公共结构)上工作时,可以获得Ad-hoc多态性,并且每种类型可能以不相关的方式运行。
public class OverloadExample {public static void main(String args []){System.out.println(add(“C”,“D”));的System.out.println(添加( “C”, “d”, “E”));的System.out.println(添加(2,3)); public static String add(String c,String d){return c.concat(d); public static String add(String c,String d,String e){return c.concat(d).concat(e); public static int add(int a,int b){return a + b; }
}
软件构建
(3)超载
3.4面向对象编程(OOP)
超载
重载方法允许您在类中重用相同的方法名称,但使用不同的参数(以及可选的不同返回类型)。 重载方法通常意味着你对那些调用方法的人来说更好一点,因为你的代码承担了处理不同参数类型的负担,而不是强迫调用者在调用你的方法之前进行转换。
3.4面向对象编程(OOP)
重载(重载)
doTask()和doTask(对象O)是重载方法。 - 要调用后者,必须将对象作为参数传递,而前者不需要参数,并使用空参数字段调用。 - 常见的错误是在第二种方法中为对象分配一个默认值,这会导致一个模糊的调用错误,因为编译器不知道要使用哪两种方法。 方法Print(对象O):人们可能希望打印时方法不同,例如文本或图片。 - 可以将两种不同的方法重载为Print(text_object T);打印(image_object P)。 - 如果我们编写所有对象的重载打印方法,我们的程序将“打印”,我们永远不必担心对象的类型,并再次调用正确的函数,调用始终是:打印(某事)。
3.4面向对象编程(OOP)
重载(重载)
函数重载是能够使用不同的实现创建同名的多个方法。 - 调用重载函数将运行适合于调用上下文的该函数的特定实现,允许一个函数调用根据上下文执行不同的任务。
重载是一种静态多态 - 使用“最佳匹配技术”解析函数调用,即根据参数列表解析函数。 - 函数调用中的静态类型检查 - 在编译时确定使用哪些方法。
3.4面向对象编程(OOP)
重载规则
函数重载中的规则:重载函数必须由arity或数据类型不同 - 重载方法必须更改参数列表。 - 重载方法可以更改返回类型。 - 重载方法可以更改访问修饰符。 - 重载方法CAN声明新的或更广泛的检查异常。 - 方法可以在同一个类或子类中重载。
3.4面向对象编程(OOP)
法律超载
public void changeSize(int size,String name,float pattern){}
以下方法是changeSize()方法的合法重载: - public void changeSize(int size,String name)检查你的理解
会发生什么?
3.4面向对象编程(OOP)
覆盖与重载
 public class Test {public static void main(String [] args){A a = new A(); A.P(10); }}
 
B级{public void p(int i){}}
 
class A extends B {//此方法覆盖B public void p(int i){System.out.println(i); }}
public class Test {public static void main(String [] args){A a = new A(); A.P(10); }}
 
B级{public void p(int i){}}
 
A类扩展B {//此方法重载B public void p(double i){System.out.println(i); }}
类A中的方法p(int i)覆盖了类B中定义的相同方法。
类A中的方法p(int i)重载了类B中定义的相同方法。
3.4面向对象编程(OOP)
覆盖与重载
不要混淆重载派生类中的方法并重载方法名称 - 当重写方法时,派生类中给出的新方法定义具有与基类完全相同的参数数量和类型 - 当方法时在派生类中,它与基类中的方法具有不同的签名,即重载 - 请注意,当派生类重载原始方法时,它仍然从基类继承原始方法
3.4面向对象编程(OOP)
覆盖与重载
重载覆盖参数列表必须更改必须不更改返回类型可以更改不能更改
例外情况可能会改变
可以减少或消除不得抛出新的或更广泛的检查异常
访问可以改变
不得限制更多(限制性更小)
调用
引用类型确定选择了哪个重载版本(基于声明的参数类型)。发生在编译时。调用的实际方法仍然是在运行时发生的虚方法调用,但编译器将始终知道要调用的方法的签名。因此,在运行时,参数匹配已经被确定,而不是方法所在的实际类
对象类型(换句话说,堆上实际实例的类型)确定选择哪个方法在运行时发生。
软件构建
(3)参数多态和泛型编程
3.4面向对象编程(OOP)
参数多态性
当函数在一系列类型上统一工作时,获得参数多态性;这些类型通常表现出一些共同的结构 - 它能够以通用方式定义函数和类型,以便它基于运行时传递的参数工作,即允许静态类型检查而不完全指定类型。 - 这就是Java中所谓的“泛型(泛型)”。 通用编程是一种编程风格,其中数据类型和函数是根据要指定的类型编写的,然后在需要时作为参数提供的特定类型进行实例化。
通用编程的核心是从具体,高效的算法中抽象出来,以获得可以与不同数据表示相结合的通用算法,以生成各种有用的软件。
3.4面向对象编程(OOP)
C ++中的模板
template
class List {
/ 课程内容 /
};
List list_of_animals;
列出 list_of_cars;
template
void Swap(T&a,T&b){
T temp = b;
b = a;
a = temp;
}
string hello =“world!”
string world =“你好”;
交换(世界,你好);
cout << hello << world << endl;
C ++标准库包括标准模板库(STL),它为常见的数据结构和算法提供模板框架。
3.4面向对象编程(OOP)
Java中的泛型
类型变量是不合格的标识符。 - 它们由泛型类声明,通用接口声明,泛型方法声明和泛型构造函数声明引入。 如果一个类声明了一个或多个类型变量,则它是通用的。 - 这些类型变量称为类的类型参数。 - 它定义了一个或多个充当参数的类型变量。 - 泛型类声明定义了一组参数化类型,每个类型参数部分都可以调用一个。 - 所有这些参数化类型在运行时共享同一个类。
3.4面向对象编程(OOP)
Java中的泛型
如果接口声明了一个或多个类型变量,则接口是通用的。 - 这些类型变量称为接口的类型参数。 - 它定义了一个或多个充当参数的类型变量。 - 通用接口声明定义了一组类型,每种类型都可以调用类型参数部分。 - 所有参数化类型在运行时共享相同的接口。 如果方法声明了一个或多个类型变量,则它是通用的。 - 这些类型变量称为方法的形式类型参数。 - 的形式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值