CS61B_Lecture9
扩展,类型转换和高阶函数
前言
implements关键字可以用来表示interface之间的关系(接口继承),而类和类之间的继承关系则需要extends来实现。
extends关键字(继承)
extends关键字可以在保持原有功能的同时让我们增加新功能,形成一个新的子类。
例如:
public class RotatingSLList<Item> extends SLList<Item>
这样RotatingSLList类会默认继承SLList的如下东西:
- 所有公共的属性
- 所有的公共方法
- 所有的公共嵌套类
但是有一些东西是不会被继承的:
- 类本身的构造函数
- private的属性和方法
那应该如何进行初始化的时候拿到初始的属性呢?
我们可以使用
super()函数来进行初始化使得其继承父类的private属性。
所有类的父类-Object
所有类都是Object类的后代。我们看以下示例:
public class Human {...}
public class TA extends Human {...}
TA显式的继承了Human,而Human则隐式的继承了Object父类。
具体继承了类似如下几个方法:
.equals(Object obj).hashCode()toString()- ...
继承可能破坏封装
假设Dog类有如下两个方法:
public void bark() {
System.out.println("bark");
}
public void barkMany(int N) {
for (int i = 0; i < N; i += 1) {
bark();
}
}
我们还有另一个版本的实现方式:
public void bark() {
barkMany(1);
}
public void barkMany(int N) {
for (int i = 0; i < N; i += 1) {
System.out.println("bark");
}
}
看似使用的时候可能没有区别,但假如我们定义了一个它的子类并重写了这个方法:
@Override
public void barkMany(int N) {
System.out.println("As a dog, I say: ");
for (int i = 0; i < N; i += 1) {
bark();
}
}
那么这里两种实现方式的结果便会大相径庭。
第二种会先调用父类的bark()->然后会调用当前Override的barkMany(1);->然后又会调用bark,最后无限递归造成栈溢出错误。
动态类型和静态类型
静态类型是编译的时候被声明的类型,动态类型指的是实际引用的对象的类型。
类型转换的原则:子类可以转换父类,但父类不能转为子类。
高阶函数
我们在61A中学过了python的高阶函数:
def tenX(x):
return 10*x
def do_twice(f, x):
return f(f(x))
但Java的高阶函数应该怎么写呢?
java中不能直接传参函数,但我们可以利用接口继承。
我们先定义一个这样的类,里面有一个接受int返回int的函数声明:
public interface IntUnaryFunction {
int apply(int x);
}
来实现以下这个函数:
public class TenX implements IntUnaryFunction {
/* Returns ten times the argument. */
public int apply(int x) {
return 10 * x;
}
}
接下来需要实现do_twice(f, x),
public static int do_twice(IntUnaryFunction f, int x) {
return f.apply(f.apply(x));
}
调用类似于这样:
System.out.println(do_twice(new TenX(), 2));

浙公网安备 33010602011771号