继承
public class Extends extends Base
如果代码中子类中存在同样方法名和参数的情况下,本类的方法会比父类的方法优先级高。
举个例子,
package chapter5;
class Base {
int num = 5;
}
public class ExtendsClass extends Base {
private int num = 6;
public int getNum()
{
return this.num;
}
public static void main(String[] args) {
ExtendsClass extendsClass = new ExtendsClass();
System.out.println(extendsClass.getNum());
}
}
输出为6。
再说构造函数
对于子类的构造函数的第一句话,都默认调用父类的无参数构造函数super()。这句话,我们举个例子,
构造两个类,
一个是A类,如下:
package chapter5;
public class A {
public A() {
System.out.println("11111");
}
public A(int a) {
System.out.println("2222");
}
}
再建造一个B类,继承自A类,
package chapter5;
public class B extends A {
public B() {
System.out.println("33333");
}
public B(int b) {
System.out.println("44444");
}
public static void main(String[] args) {
B obj1 = new B();
System.out.println("======");
B obj2 = new B(5);
}
}
此时,输出结果为:
11111
33333
======
11111
44444
即:
在继承自某一个父类构造函数时,默认一开始调用的是super()
,即无参数的父类构造函数。此时B类代码等价如下:
package chapter5;
public class B extends A {
public B() {
super();//看这里,增加super();,Java自动添加无参数的构造函数
System.out.println("33333");
}
public B(int b) {
super(); //看这里,增加super();,Java自动添加无参数的构造函数
System.out.println("44444");
}
public static void main(String[] args) {
B obj1 = new B();
System.out.println("======");
B obj2 = new B(5);
}
}
如果,将B类中的带参数构造函数中的super()
更改为super(b);
, 此时obj2继承调用时会调用父类的带参数构造函数,此时输出不一样了。
举个例子,
package chapter5;
public class B extends A {
public B() {
super();
System.out.println("33333");
}
public B(int b) {
super(b);
System.out.println("44444");
}
public static void main(String[] args) {
B obj1 = new B();
System.out.println("======");
B obj2 = new B(5);
}
}
此时输出结果为:
11111
33333
======
2222
44444
抽象类和接口
抽象类
抽象类的定义
举个例子,
接口定义
说接口是特殊的类,是因为接口也是class文件,编译出来也是.class文件。
接口里的方法都是空的。那么接口与抽象类来说,
举个例子,
首先定义一个接口Animal,
package chapter5.abstractAndInterface;
public interface Animal {
public void eat();
public void move();
}
接下来,定义一个健康类Cat,实现自Animal,
⚠️ 健康类实现自接口(implements)
⚠️ 健康类Cat必须实现接口Animal里所有的方法。
package chapter5.abstractAndInterface;
public class Cat implements Animal{
public void eat() {
System.out.println("cat: i can eat");
}
public void move() {
System.out.println("cat: i can move");
}
}
抽象类与接口的关联
定义一个实现自Animal的抽象类,【因为其中的eat方法没有具体实现,因此该类必须要是抽象类】
package chapter5.abstractAndInterface;
public abstract class LandAnimal implements Animal {
public abstract void eat();
@Override
public void move() {
System.out.println("I can walk by feet");
}
}
继承自抽象类,实现自接口的健康类的写法怎么写呢?
⚠️ 继承(extends)必须在接口 实现(implements)之前,即 public class Rabbit extends LandAnimal implements ClimbTree
。否则,报错
package chapter5.abstractAndInterface;
// LandAnimal 和 ClimbTree 里的方法都必须要实现
public class Rabbit extends LandAnimal implements ClimbTree {
@Override
public void climb() {
System.out.println("Rabbit: I can climb");
}
@Override
public void eat() {
System.out.println("Rabbit: I can eat");
}
}
接口继承
既然接口是一种“特殊”的类,那么接口是否可以继承自另一个接口呢?答案是肯定的。
举个例子,
定义一个接口CatFamily
,该接口继承于Animal, ClimbTree
。那么具体实现如下:
package chapter5.abstractAndInterface;
// 接口可以继承于多个接口
public interface CatFamily extends Animal, ClimbTree {
// eat()
// move()
// climb()
}
接下来,实现一个健康类Tiger
,实现自接口CatFamily
,那么该类就要实现该接口内全部方法。如果不全部实现,那么该健康类Tiger
必须为抽象类(abstract Tiger
)
package chapter5.abstractAndInterface;
public class Tiger implements CatFamily{
@Override
public void eat() {
System.out.println("Tiger: I can eat");
}
@Override
public void move() {
System.out.println("Tiger: I can move");
}
@Override
public void climb() {
System.out.println("Tiger: I can climb");
}
}