HIT软件构造复习:chapter7

本章讲了OOP面向对象编程,是ADT的具体实现技术。

对象指的是显示存在的真实的个体,有状态和行为来描述。将之抽象为ADT,用属性和方法模拟实现。

将一些由共同点的相似个体抽象成类,类包含这些个体的公共特征。类一般由名字、属性、方法构成。

类的成员变量和方法是抽象的,定义一般加static,用类调用即可,类的实例的成员变量和方法是具体的,用声明的实例进行调用。对于类方法的调用,Java虚拟机会自动为类所有的静态方法创建一个形式实例进行调用,所有方法可以视为均由这个实例进行调用。

其中静态方法无法直接调用非静态成员。

接口:与类很相似,但一般只有方法没有属性,且方法只有定义,并没有具体实现(不过较新版本的Java已经允许接口之中的部分静态方法有具体实现)。接口之间可以有继承与扩展,但是Java不支持多继承,为了弥补这点,一个类可以实现多个接口,从而具备它们的所有方法,一个接口也可以有多个实现类。

接口用于确定ADT的规约,类用于ADT的实现,当然也可以不用接口,直接用类实现ADT的定义+实现,但是一般不这么做,更倾向于用接口来定义,用类实现。例如,更倾向于

Set<type> set = new HashSet<type>();

而非

HashSet<type> set = new HashSet<type>();

类必须完成对应接口中所有定义的方法的实现,否则会在编译阶段报错(静态检查)。但是这样会导致有的方法重复实现,为了简便,可以用@default在接口实现这部分会重复的功能,这些功能就不需要在具体实现类中再次实现。但是仍然可以在类中实现这些方法,这样会以类中的实现覆盖掉@default实现

接口中没有构造函数,因为接口可能会有多个实现类,而构造函数需要确定具体的构造类型(与它所在的类的类型一致)。但是也可以将具体类型封装到接口的方法内部,而不体现在签名:

return new 具体类型();

之前说到的Java较新版本允许有静态方法的实现就是为了弥补这种封装不彻底的问题,这些实现的方法直接用接口调用即可。

类可以有接口中没有定义的方法,新增一些独特的功能,当然这些功能的实现不能改变RI。

封装/信息隐藏

只暴露接口,客户端只能使用接口定义的方法,且无法直接访问属性,一般用get方法返回。

但是客户端可以绕过接口访问其他非接口成员。

成员的可视性:

作用域当前类同一包内子孙类(不同包)其他包
public
proteced×
default××
private×××

继承:保存父类中的通用的方法,并且可以有自己独特的方法,类似于生物中的遗传。一般字类用一个三角箭头指向父类表示继承关系。继承之后无需重复定义父类的属性、方法。

A继承B: Class A extends B{...}

**泛化:跟继承一样,只不过继承是编程中的术语,泛化是建模中的术语。

严格继承:只能添加新方法,或重写非超类的方法,不可重写超类中方法,即前面+fianl(超类方法:public、protected)

重写:overriding,专业术语,不可修改。重写仅修改方法实现的细节,签名属性不变,即返回值、函数名、参数不变,要遵循方法的本意,不能随意实现。在运行时根据调用者是字类还是父类决定调用父类中的还是字类中重写过的方法。

如果一个方法在不同的实现类当中具体细节差异不大,那么一般会在父类型里实现,然后大多数字类型可以直接复用,少数需要重写的在字类中重写。也有可能父类型中方法的实现为空,每个字类型都需要重写,这个时候就代表各个字类对于这个方法没有共性,都需要重写

很显然,越往父类方向越抽象,越往子类方向越具体。

在子类的方法中如果调用了父类的方法,用super.method调用(因为子类可能对同名方法进行了重写,用于区分是子类的方法还是父类的)特殊的,在调用构造函数时,必须在第一行,且格式为super(参数);调用本类的构造函数

重写之后的方法,其规约必须更严格或者不变,抛出异常不能有新的情况,通俗点说,不能违背父类的方法的要求。并且重写之后的可见性不可降低。@override会被识别,自动识别重写的方法的签名与父类是否一样。

ADT的泛型化:即ADT的部分属性、操作的数据类型标识可以任意

抽象方法:就是方法,但是只有定义,没有实现

抽象类:没有实例化(不能用new 产生一个实例)。一样的继承抽象父类的时候,要求必须实现全部父类中的抽象方法。和正常的类一样,重复性较高的可以在父类实现,子类不同的在自己类中重写。或是子类之间差异较大的,父类只予以定义,子类各自实现。抽象XX定义时,在类型名字前加上abstract。

多态

1.特殊多态:即重载,一个方法有多个同名实现,但是签名不同,其中参数列表一定要不同,返回值、可见性、抛出异常可以不同(若签名相同,则无法判断该调用哪个)。重载可以发生在父类、子类中,在编译阶段根据调用时传入的参数匹配该执行的方法,因此也称为静态多态。与重写不同,重写的签名必须严格一致且在运行时进行动态检查。

子类的对象可以调用父类中的方法,父类实例无法调用子类独有的,但是当父类由子类实例实现时,可以调用子类中的方法(用实例调用)。

2.参数化多态:一个类型的变量可以代表多个类型,即泛型化,表现为对多个类型的同样的行为。在编译成class时根据指定的类型确定泛型化处的具体类型并完成替换,其中,泛型类和泛型接口在创建实例时指定,泛型方法在调用时指定。

泛型方法:在可见性标识和函数返回值类型之间用<T>表示泛型方法,这个T若与参数泛型T相同也无碍,它们并不表示相同的类型的意思。

非泛型的方法指配了一定的类型之后,不再发生改变。

静态方法无法调用泛型所在泛型类中定义的泛型变量。想要使用,必须将此方法改装成泛型方法。

3.子类型多态:也称为包含多态,一个变量的名字可以代表多个类的实例(子类型)。例如List可以由ArrayList,也可以是LinkedList。不同类型的对象可以统一处理,从而能够隔离变化

任何基类出现的地方,其子类一定也能出现/替换

一个类只有一个父类,但是可以实现多个接口。

当类A的规约不弱于类B的规约时,每一个A的实例都可以认为是B的一种,可以称A是B的一个子类

子类型的规约不能弱于超类型的规约

通配符:?,表示类型未知,但是可以对这个未知加以修饰,例如此位置必须得继承某个类:

? extends ClassA

Object类:所有类的基类,有equals()、hashcode()、toString()三个方法,分别实现判断this与另一个对象是否"相等",求其哈希值(放入哈希容器中用于定位的编码)、将对象属性转化为字符串以便输出,不同的类根据不同要求可以对这三个基本方法进行重写。

其中对equals的重写在第八章等价性会详细介绍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值