Java 继承
继承是所有面向对象语言的基石。
继承就是子类继承父类的特征和行为,使得子类的实例具有父类的实例域和方法,或者子类继承父类的方法,使得子类具有父类相同的行为(实际上子类除了能继承父类的属性和方法,还可以对方法进行重写)。
类继承格式
和 JavaScript 一样,类通过关键字 extends 继承,语法如下:
class Child extends Father {}
继承的特性
继承很重要的一点作用就是解决代码复用问题,提高代码的复用性和可维护性。
特性:
- 子类拥有父类的feiprivate属性。
- 子类还可以定义自己的属性和方法。
- 子类可以自己实现父类的方法(重写)。
- java不支持
多继承
,但支持多重继承
。 - 继承提高了类之间的耦合性,但是耦合度如果太高会造成代码独立性差。
继承关键字
继承可以使用extends
和implements
这两个关键字来实现继承,而且所有的类都继承于java.lang.Object
,当一个类没有继承其他类则默认继承Object
。
extends关键字
在java中,类的继承是单继承,一个类只能拥有一个父类,可以使用extends关键字继承:
//父类
public class Animal {
public String name = "animal";
public int age = 10;
private String gender = "male";
public void sayName() {
System.out.println("saying " + name);
}
public void sayGender() {
System.out.println(gender);
}
}
//子类
public class Cat extends Animal {
public static void main(String[] args) {
Cat lion = new Cat();
System.out.println(lion.age); // 10
System.out.println(lion.name);// animal
// System.out.println(lion.gender);// 报错:The field Animal.gender is not visible 因为父类中gender是private修饰的
lion.sayName(); // saying animal
lion.sayGender(); //male
}
}
implements关键字
类似于TypeScript,implements关键字用来继承接口(interface),和extends关键字不同的是,implements关键字可以用来继承多个接口:
class Animal implements Interface1, Interface2{
}
例如:
// 接口
public interface InterfaceA {
void sayName();
}
// 类实现接口
public class ImplTest implements InterfaceA {
public void sayName() {
System.out.println("my name is ImplTest");
}
public static void main(String[] args) {
ImplTest ipTest = new ImplTest();
ipTest.sayName(); // my name is ImplTest
}
}
super和this关键字
super关键字:可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字: 指向自己的引用。
比如下面这个例子:我们创建Bird类并且继承上面定义的Animal类,然后重写sayName方法,然后在sayNames里面分别调用自己和父类的sayName方法:
public class Bird extends Animal {
//子类Bird重写父类Animal的sayName,需要注意的是重写方法的时候方法的修饰符和返回值类型不能变
public void sayName() {
System.out.println("这是子类重写的sayName");
}
void sayNames() {
this.sayName(); // 这是子类重写的sayName
super.sayName(); // saying animal
}
public static void main(String[] args) {
Bird bd = new Bird();
bd.sayNames();
}
}
构造器
子类只会调用(显式或者隐式)父类的构造器而不会去继承。如果父类的构造器带参数,则必须在子类的构造器中显式地通过super
关键字来调用父类的构造器配以适当的参数列表。
如果父类构造器没有参数,则系统会自动调用父类的无参构造器。
//父类Person
public class Person {
public String name;
public String gander;
public int age;
public String className;
public void say() {
System.out.println(
"My name is" + name + ", gander is " + gander + ", age is " + age + ", class name is" + className);
}
public Person(String name, String gander, int age) {
this.name = name;
this.gander = gander;
this.age = age;
this.className = "PERSON";
}
public static void main(String[] args) {
Person joey = new Person("Joey", "Male", 18);
joey.say(); // My name isJoey, gander is Male, age is 18, class name isPERSON
}
}
//子类Chinese
public class Chinese extends Person {
// 这里因为父类Person的构造器是带参数的,所以这里必须显式声明构造器,并且调用super方法传入合适的参数列表
public Chinese(String name, String gander, int age) {
super(name, gander, age);
}
public void say() {
System.out.println("Chinese 重写的say方法");
super.say();
}
public static void main(String[] args) {
Chinese hanshufei = new Chinese("Hanshufei", "男", 18);
hanshufei.say();
// Chinese 重写的say方法
// My name isHanshufei, gander is 男, age is 18, class name isPERSONON
}
}