目录
继承的目的:抽取共性,实现代码的复用
关键字:extends
修饰符 class 子类 extends 父类 {}
例如:我们要写一段代码来实现对不同动物行为的控制: 小猫:喵喵叫,吃饭,睡觉,奔跑;
小狗:汪汪叫,吃饭,睡觉,奔跑。
以前我们的做法是:分别写一个类来描述小猫和小狗的行为。但是我们发现,它们之间存在大量重复的特征(吃饭,睡觉,奔跑),产生了大量重复的代码,这时我们就可以使用继承来实现对这部分重复特征的的抽取,实现代码的复用。
class Anilmal {
public String name;
public void eat(){
System.out.println(name+"在吃饭");
}
public void run(){
System.out.println(name+"在奔跑");
}
public void sleep(){
System.out.println(name+"在睡觉");
}
}
class Dog extends Anilmal{
public void sonund(){
System.out.println(name+"汪汪叫");
}
}
class Cat extends Anilmal{
public void sonund(){
System.out.println(name+"喵喵叫");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
dog.name = "小黄";
cat.name = "小花";
dog.run(); dog.eat(); dog.sonund(); dog.sleep();
cat.run(); cat.eat(); cat.sonund(); cat.sleep();
//从anilmal中继承其name,run,eat,sleep属性,通过不同的子类调用这些属性,达到了代码的复用
}
}
子类(也叫派生类)继承父类后,会继承父类(也叫基类/超类)的成员方法和成员变量,继承之后,子类可以复用父类中成员(可以看作将父类中的成员增加到子类中)。
**子类不会继承父类的静态成员
继承方式
对子类和父类成员的访问
1.子类和父类无相同的成员变量或方法(这里的不相同指成员变量不同名,成员方法不同名或同名但参数不同(方法的重载)时:
根据变量名或者方法名加参数先从子类中找,子类没有时再从父类中找,找不到就报错。
2.子类和父类存在相同的成员变量或方法(方法名相同且参数相同)时:
只访问子类的不访问父类的。
总结:满足就近原则,优先在子类中找,没有才从父类中找
强调:我们这里的访问都是从测试类和子类的角度看,继承是单向的访问关系,父类只能访问自己的成员方法和变量
class Farther{
String name = "er";
int a = 2;
int b = 0;
public void sout(){
System.out.println(name);
}
}
class Son extends Farther{
String name = "yi";
int a = 1;
public void sout(){
System.out.println(name);
}//子类和父类的成员变量相同,满足就近原则,输出子类的name
}
public class Text {
public static void main(String[] args) {
Son son = new Son();
son.sout();//子类和父类的成员方法相同,调用子类的sout方法
System.out.println(son.a);
System.out.println(son.name);
//子类和父类的成员变量相同,输出子类的a和name
System.out.println(son.b);
//先找子类发现子类没有,在找父类,发现有输出父类的b
}
}
那么当存在子类和父类的成员相同时我们如何访问父类成员呢?
super
作用:在子类方法中访问父类的变量
***在子类中使用
***非静态方法中使用
class Farther{
int a = 2;
}
}
class Son extends Farther{
int a = 1;
public void sout(){
System.out.println(super.a);
}//输出父类的a
}
继承的构造方法
原则:子类对象中成员是由两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子 肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整 ,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。
当子类构造函数第一句不是对父类构造函数调用且父类构造函数无参时,系统会自己在第一行写一个super()来调用父类构造函数
总结:你要写一个继承,你对这个继承的类进行实例化时,先进行子类构造函数的查询,你没写子类的构造函数时,系统会自己给你写,系统写的这个构造函数第一句话一定是super(),这就规定了你的父类的构造函数一定是无参的,同样的,你如果也没在父类中写构造函数系统会自己写一个无参的构造函数;如果你写了子类的构造函数,这个构造函数一定是先调用父类的构造函数,父类有构造函数且有参时你必须选择合适的方法调用父类构造方法,无参或没有构造函数时写一个super()就行,你没写系统也会自己自动给你加。
*当作为调用构造方法来使用时,this()和super()都要求出现在第一行,所以不能同时出现,意味着在子类构造方法中不能出现this()