软件构造OOP总结
软件构造OOP总结
基本概念
Object:两部分组成。1.State,object中的数据域 2.Behavior在java中可以视为方法
Class :定义了object中的那两部分。这里着重介绍下Class中的方法:
- 类方法,即被static修饰的方法
- 实例方法,除了类方法以外的方法

特别注意其中提到的,静态方法无法调用非静态成员(没有Static修饰的),只能调用静态成员
此外还要注意的就是它们在Java中是如何创造的,如下图
接口
首先我们要明白接口是ADT中最抽象的部分,接口中只有方法的定义,没有实现(Java8之后对其进行了扩展为了保护表示独立性但是接口在定义中可以是没有实现的)。接口之间可以扩展与继承,同时JAVA中一个类可以实现多个接口(从而具备多个接口中的方法),一个接口可以有多种实现类,实现是应该加上implement关键字。
接着我们要弄清楚类与接口在ADT中的地位。
接口:确定ADT规约;类:实现ADT,也可以不需要接口直接使用类作为ADT,这样该类中既有ADT定义也有ADT实现。怎么做是取决于对复用的要求。实际中更倾向于使用接口来定义变量。
需要注意的是接口存在问题,其打破了抽象边界,接口定义中没有包含constructor,也无法保证所有实现类中都包含了同样名字的constructor。例如List接口我们要用其定义变量就需要显示的调用实现类,这是一种表示泄露。
因此**JAVA8中允许接口中存在静态方法从而解决了这个问题。
同样的我们也很容易想到由于接口中的每个方法在所有类中都要实现会导致部分方法的重复实现。我们可以通过default方法,在接口中统一实现某些功能,无需在各个类中重复实现它。 default 方法的典型使用方式:以增量式的为接口增加额外的功能而不破坏已实现的类。
封装与信息隐藏
一个重要的区分设计好的与坏的模型的方法就是其隐藏内部数据与实现的程度。我们主要介绍通过接口来实现这一准则。
我们需要做到:使用接口类型声明变量,客户端仅使用接口中定义的方法,客户端代码无法直接访问属性。
提到信息隐藏很重要的一项就是,对于成员可见类型的修饰符。列表如下:
需要注意的是我们在写程序进行该动是可以将private的成员变为public的成员,但是不能反过来,为了防止访问被拒绝。
继承与重写
继承是代码复用的方法,当一个类继承了超类时,超类中的public与protected标志的成员默认在子类中可以访问(default要看是不是在一个包内)。
接着我们需要明确什么类可以不可以被继承,加了final关键字的类无法被继承。
重写
我们先说明以下继承的方式:有严格与非严格继承之分我们着重介绍严格继承。
严格继承子类只能添加新方法,无法重写超类中的方法。JAVA中通过final关键字实现。加了final的数据域在初次赋值后无法被再次赋值,一个加了final关键字的方法无法被子类重写。
接着介绍重写的概念:重写是一种语言特性,它允许子类提供某方法(由其超类提供)的特定实现。
注意以下几个特征:1.被重写的函数与原函数有相同的签名 2.实际运行时调用哪个方法由运行时决定(即看用哪个类实现),这就意味着静态检查不会检查这部分。
我们在子类继承父类的时候可以复用父类的方法,有以下两种形式:
-
constructer中复用父类的constructer,(1)这是声明要放在第一行,(2)其参数放在括号里。在子类中用子类自己的constructor也是一样的要求
-
其他方法,我们可以用super关键字调用父类的除constructor的方法,用this调用子类中的除constructor的方法
然后就是需要注意的时重写的方法不能改变原方法的本意,如下例:
同时还需要注意的是由于二者可以在可见类型修饰符上有不同所以考虑到可以用子类代替代替父类,此时子类的修饰符要比父类中的可见度更高。以下是反例:
同时在编写程序的时候可以在子类中重写的方法前加@Override然后compiler 会检查覆盖方法和被覆盖的方法签名是否完全一致
抽象类
首先明确抽象方法的概念,抽象方法是一种只有签名但是没有实现的方法。而抽象类就是包含至少一种抽象方法的类。抽象类与接口一样不能实例化,继承某个抽象类的子类在实例化时,所有父类的方法均必须实现。(当然我们也可以用抽象类实现接口,也可以用抽象类实现抽象类实现抽象类)
设计抽象类时要注意:
- 如果某些操作是所有子类型都共有, 但彼此有差别,可以在父类型中设计 抽象方法,在各子类型中重写
- 所有子类型完全相同的操作, 放在父类型中实现,子类型中无需重写。
- 有些子类型有而其他子类型无的操作,不要在父类型中定义和实现,而应在特定子类型中实现。
我们可以把接口认为是一个其中只含有抽象方法的抽象类。
多态,子类型,重载
多态的类型
- 特殊多态(Ad hoc polymorphism):一个方法可以有多个同名的实现(方法重载)
- 参数化多态(Parametric polymorphism):Parametric polymorphism
- 子类型多态:一个变量名字可以代表多个类的实例
特殊多态与重载
重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型,价值:方便client调用,client可用不同的参数列表,调用同样的函数。
重载时一种静态多态,编译器会根据参数列表进行最佳匹配,同时会进行静态类型检查,与重写不同在编译阶段决定要运行哪个方法
重载的规则及应该怎么书写重载
要注意这里不同的参数列表是指变量的类型,不同而不是指其变量名不同。由于重载的方法与原方法完全时不同的方法所以其他属性均可以改变
特别注意的时发生在父类与子类之间的重载,由于重载时在静态检测时就会检查使用哪个方法所以其是由变量的类型决定的,如下图,我们在调用ua.doStuff()时使用Animal类型定义由House子类型实现的类,那么会调用以Animal为变量的方法。
接下来,把重写与重载放一起进行练习:
其中1,2,4行比较简单。第3行我们会发现使用了方法的重载,用House子类定义了Animal类型的变量所以实现时会用重载的方法。第5行第6行特别需要注意,原Animal类当中是没有重载的eat(String)方法的,所以不管用什么类实现均会报错。
特别注意接口与抽象类是不能用自己的new方法进行实例化的,这样静态检测时会报错。第23行比较简单,第四行与上面是类似的,一个变量无法调用与其定义中不符的方法,无论其用什么实现。
重载与重写的区别:
参数多态与范型编程
参数多态性是指方法针对多种类型时具有同样的行为 (这里的多种类型应具有通用结构),此时可使用统一的类型变量表达多种类型。在运行时根据具体指定类型确定具体类型(编译成class文件时,会用指定类型替换类型变量“擦除”)。
泛型类:类中声明了一个或者多个范型变量。这些类型变量称为类的类型参数。在编写这类类是先将其范型的声明放在类名之后在类中声明变量时将类型换位对应的范型变量,如下我们可以在使用时将T换为Integer等:
范型接口:与范型类类似当接口声明了一个或者多个范型变量时将其称为范型接口。当我们具体实现它时可以为该范型传入具体的值也可以仍按照范型来。
子类型多态
一个类只有一个父类,但可以实现多个接口,在图中表现为对于类来说其只能指向一个父类。
当B为A的子类型时当且仅当B的规约强于A。
子类型多态:不同类型的对象可以统一的处理而无需区分。LSP原则。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】