一、继承的概念
继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法
例:
public class Penguin {
// 定义属性
private String name;
private int health;
private int love;
private String sex;// 构造方法
public Penguin() {
}public Penguin(String name, int health, int love, String sex) {
this.name = name;
this.health = health;
this.love = love;
this.sex = sex;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public int getHealth() {
return health;
}public void setHealth(int health) {
this.health = health;
}public int getLove() {
return love;
}public void setLove(int love) {
this.love = love;
}public String getSex() {
return sex;
}public void setSex(String sex) {
this.sex = sex;
}// 定义一个方法输出Penguin对象的name、health、love属性值
public void printInfo(){
System.out.println("昵称:"+this.getName()+",健康值:"+this.getHealth()+",亲密度:"+this.getLove());
}
}
从上述案例来看有很多重复的代码,这时我们就可以使用继承来优化,将重复代码抽取到父类中
父类和子类的概念
1)多个类中存在相同的属性和方法,可以抽取出来,放在一个公共类中,这个公共类称之为父类
2)那么,多个类中就不需要再定义那些相同的属性和方法,只需要通过extends关键字继承父类,就可以使用父类中的属性和方法
3)在这个多个类中只修要定义自己类特有的属性和方法,这多个类称之为子类
二、继承的实现
1、编写父类
访问修饰符 class Pet {
// 公共的属性和方法
}
2、编写子类
访问修饰符 class Dog extends Pet {
// 子类特有的属性和方法
}
3、直接父类
继承是Java中实现代码重用的重要手段之一
1)Java中类与类之间的继承关系只能是单根继承,即一个类只能有一个直接父类
2)类与类之间可以间接继承:A继承B,B继承C,那么A间接继承C,A可以使用B和C中的属性和方法
4、子类访问父类
1)访问父类构造方法
super(); // 访问父类中的无参
super(name); // 访问父类中的有参
2)访问父类属性
super.name;
3)访问父类方法
super.print()
5、super关键字
1)使用super关键字,super代表父类对象
2)super只能出现在子类的方法和构造方法中
3)super调用构造方法时,必须是第一句
4)不可以访问父类中定义为private的属性和方法
例:
package com.learn.demo02;
public class Pet {
// 定义Dog类、Penguin类、Cat类、...等类中相同的代码
private String name;
private int health;
private int love;public Pet() {
}public Pet(String name, int health, int love) {
this.name = name;
this.health = health;
this.love = love;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public int getHealth() {
return health;
}public void setHealth(int health) {
this.health = health;
}public int getLove() {
return love;
}public void setLove(int love) {
this.love = love;
}// 定义一个方法输出name、health、love属性值
public void printInfo(){
System.out.println("昵称:"+this.getName()+",健康值:"+this.getHealth()+",亲密度:"+this.getLove());
}
}
package com.bdqn.demo02;
public class Penguin extends Pet{ // 使用extends继承父类Pet
// 这里只需要定义Penguin类中特有的属性
private String sex;public Penguin() {
}public Penguin(String name, int health, int love, String sex) {
super(name, health, love); // 使用super关键字访问父类中的属性
this.sex = sex;
}public String getSex() {
return sex;
}public void setSex(String sex) {
this.sex = sex;
}
}
测试:
package com.learn.demo02;
public class Test {
public static void main(String[] args) {
// 创建Dog类对象
Dog dog1 = new Dog();
// 说明:setName()、setHealth()、setLove()方法在Dog类中不存在,但是在Pet类中存在,而Dog类继承了Pet类,所以Dog类对象可以调用Pet类中的方法
dog1.setName("旺财");
dog1.setHealth(90);
dog1.setLove(100);
// setStrain()方法在Dog中存在,可以调用
dog1.setStrain("金毛");// 通过getXxx()方法获取信息
// 说明:getName()、getHealth()、getLove()方法在Dog类中不存在,但是在Pet类中存在,而Dog类继承了Pet类,所以Dog类对象可以调用Pet类中的方法
System.out.println(dog1.getName());
System.out.println(dog1.getHealth());
System.out.println(dog1.getLove());
// getStrain()方法在Dog中存在,可以调用
System.out.println(dog1.getStrain());// 说明:printInfo()在Dog类中不存在,但是在Pet类中存在,而Dog类继承了Pet类,所以Dog类对象可以调用Pet类中的方法
dog1.printInfo();System.out.println("-------------------------------------");
// 创建Penguin类对象
Penguin penguin1 = new Penguin();
// 给属性赋值
// setName()、setHealth()、setLove()方法在Penguin类中不存在,但是在Pet类中存在,而Penguin类继承了Pet类,所以Penguin类对象可以调用Pet类中的方法
penguin1.setName("QQ");
penguin1.setHealth(100);
penguin1.setLove(99);
// setSex()方法在Penguin中存在,可以调用
penguin1.setSex("公");// 输出Penguin对象属性信息
// getName()、getHealth()、getLove()方法在Penguin类中不存在,但是在Pet类中存在,而Penguin类继承了Pet类,所以Penguin类对象可以调用Pet类中的方法
System.out.println(penguin1.getName());
System.out.println(penguin1.getHealth());
System.out.println(penguin1.getLove());// getSex()方法在Penguin中存在,可以调用
System.out.println(penguin1.getSex());// printInfo()在Penguin类中不存在,但是在Pet类中存在,而Penguin类继承了Pet类,所以Penguin类对象可以调用Pet类中的方法
penguin1.printInfo();
}
}
三、子类访问父类成员案例
package com.learn.demo03;
public class Father {
// 定义属性
private String name;
private int age;
public char gender;public Father() {
System.out.println("Father类中的无参构造方法");
}public Father(String name, int age) {
System.out.println("Father类中的有参构造方法");
this.name = name;
this.age = age;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public int getAge() {
return age;
}public void setAge(int age) {
this.age = age;
}// 定义一个方法
public void m1(){
System.out.println("Father类中的一个方法m1()");
}
}
注意:
在子类的构造方法中,如果没有显示调用父类的哪一个构造方法,默认调用父类的无参构造方法,并且是隐藏调用
(自动调用还怪高级)
package com.learn.demo03;
public class Son extends Father{ // 继承父类Father
// 定义子类中特有的属性
private String gameAccount;public Son() {
/*
* 在子类构造方法中,可以使用super关键字调用父类中的构造方法
* 在子类的构造方法中,如果没有显示调用父类的哪一个构造方法,默认调用父类的无参构造方法,并且是隐藏调用
* 使用super关键字调用父类中的构造方法语句必须写在子类构造方法中的第一行
* */
super();
System.out.println("Son类中的无参构造方法");
// super(); super调用构造方法需要放在第一句
}public Son(String name, int age, String gameAccount) {
// 显示调用父类中的某一个构造方法
super(name, age); // name、age属性在父类中定义的用super关键字调用
System.out.println("Son类中的有参构造方法");
this.gameAccount = gameAccount;}
public String getGameAccount() {
return gameAccount;
}public void setGameAccount(String gameAccount) {
this.gameAccount = gameAccount;
}// 在子类中定义一个方法
public void m2(){
/*
* super代表父类对象,可以调用父类中的构造方法、属性、普通方法
* */
System.out.println("Son类中的方法");
// 调用父类中的gender属性
System.out.println(super.gender);
// 调用父类中的m1方法 (调用普通方法没写第一行嘞)
super.m1();
}
}
package com.learn.demo03;
public class Test {
public static void main(String[] args) {
// 使用无参构造方法创建Son类对象
Son son = new Son();
// 输出结果
// Father类中的无参构造方法
// Son类中的无参构造方法// 通过son对象调用Son类中的m2()方法
son.m2();System.out.println("----------------");
// 使用有参构造方法创建Son对象
Son son1 = new Son("张三",23,"131256479");}
}
1、继承下的构造方法
继承条件下的构造方法的调用规则
1)子类构造方法没有通过super显式调用父类的有参构造方法,也没通过this显式调用自身其他构造方法
系统默认调用父类的无参构造方法
2)子类构造方法通过super显式调用父类的有参构造方法
执行父类相应构造方法,而不执行父类无参构造方法
3)子类构造方法通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则
2、子类能继承父类
1)继承public修饰的属性和方法,不管子类和父类是否在同一个包里
2)继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里
(默认权限修饰符,包级私有)
例:
package com.learn.demo04;
public class Father {
public String name;
protected int age;
char gender;
private String phone;
}
package com.learn.demo04;
public class Son extends Father {
}
package com.learn.demo04;
public class Test {
public static void main(String[] args) {
// 创建Son类对象
Son son = new Son();
son.name = "张三"; // public
son.age = 20; // protected
son.gender = '男'; // 默认修饰符
// Father类中的phone使用private修饰,只能在Father类中直接访问,出来Father类不能直接访问,子类也不行
// son.phone = "13245678965";
}
}
package com.learn.demo05;
import com.bdqn.demo04.Father; // 导包
public class Son extends Father {
public static void main(String[] args) {
Son son = new Son();
// 这样写可以访问
son.age = 12;
}
}
package com.learn.demo05;
public class Test {
public static void main(String[] args) {
// 创建demo05包中的Son类对象
Son son = new Son();
// 访问Father类中的属性
son.name = "李四";
// son.age = 30; // protected 只能在同包内访问,同包子类访问
// son.gender = '男'; // 默认修饰符
// son.phone = "132464565656"; // private只能在本类中
/*
访问修饰符protected
1)可以修饰属性和方法
2)本类、同包、子类可以访问
*/
}
}
3、子类不能继承父类
1)private成员
2)子类与父类不在同包,使用默认访问权限的成员
3)构造方法
即子类不能创建父类的对象