博主:_LJaXi Or 東方幻想郷
专栏: Java | 从入门到入坟
Java 继承
- 继承的特点 \ 介绍 ❓
- 特点 ♊
- 继承的使用方式 🔞
- 避免重复方法
- 子类访问父类的成员变量 🈲
- 子类访问父类的成员变量(直接访问)
- 访问父类与子类同名的成员变量
- 子类访问父类的成员方法(直接访问)
- 访问父类与子类中同名的方法(优先访问子类)
- super 关键字 🔞
- 子类构造器 🈲
继承的特点 \ 介绍 ❓
特点 ♊
- 继承发生在多个类之间
- Java允许单继承,多层继承(B类继承A类,C类继承B类)
- 被继承的叫做父类(基类 、超类),继承的叫做子类(派生类)
- 子类可继承非私有属性和方法
- 子类不能继承父类的构造函数,但是可以调用父类的构造函数
- 调用带有参数的构造方法时,使用super(n1…)
继承的使用方式 🔞
在Java中可以使用 extends 关键字 来声明,一个类是从另外一个类中继承下来的
如下代码
public class A {
}
// 这段代码说明 B 继承了 A 类
public class B extends A {
}
* 当子类继承了父类之后,子类就可以调用父类中的方法,如下代码所示
public class Demo {
public static void main(String[] args) {
// 程序入口函数
// new 关键字 进行类实例化
Cat cat = new Cat();
// 子类调用父类方法
cat.eat(); // 吃东西
}
}
// 父类Animal
public class Animal {
public void eat() {
System.out.println("吃东西")
}
}
// 子类Cat继承父类Animal
public Cat extends Animal {
}
避免重复方法
比如说有两个类,其中的方法是相同的功能
定义一个猫类,一个狗类
// 猫类
public class Cat {
public String name;
public int age;
public void say() {
System.out.println(name + "喵喵叫");
}
public void eat() {
System.out.println(name + "吃东西");
}
}
// 狗类
public class Dog {
public String name;
public int age;
public void say() {
System.out.println(name + "汪汪叫");
}
public void eat() {
System.out.println(name + "吃东西");
}
}
发现 Cat 与 Dog类有相同的成员变量,和相同的成员方法,所以我们提取出一个主类,Animal,避免重复使用代码,Animal父类包含Cat和Dog类中的成员属性
public class Animal {
public String name;
public int age;
// cat 和 dog类中公共的成员方法
public void say() {
System.out.println(name + "在叫");
}
public void eat() {
System.out.println(name + "吃东西");
}
}
现在父类中有两个成员方法,我们可以修改一下cat类和dog类,如下代码所示
// 狗类
public class Dog extends Animal {
public void say() {
System.out.println(name + "汪汪叫");
}
}
// 猫类
public class Cat extends Animal {
public void eat() {
System.out.println(name + "吃东西");
}
}
子类访问父类的成员变量 🈲
子类使用extends将父类的成员变量及方法继承了下来
子类访问父类的成员变量(直接访问)
//父类
public class Animal {
//Dog类和Cat类公共的属性
public String name;
public int age;
//Dog类和Cat类公共的方法
public void eat() {
System.out.println(name + "吃饭");
}
}
//子类
public class Dog extends Animal {
//这里的colour就是子类与父类不同名的成员变量
public String colour;
//子类Dog独有的方法
public void dogCall(){
System.out.println(name + "汪汪汪");
}
}
访问父类成员的属性被private修饰时,前面介绍过被private修饰的变量只能在同一个包同一个文件的同一个类下使用,那么此时如何访问:可以利用Generate进行封装
在父类中的age属性使用private修饰,即使DOG继承了父类,也不能对这个属性进行访问,解决办法是对这个属性进行封装
private 声明的属性不能直接访问,但可以通过类提供的方法进行访问
//父类
public class Animal {
//Dog类和Cat类公共的属性
public String name;
private int age;
//右键选择Generate进行封装
public int getAge() {
return age;
}
//右键选择Generate进行封装
public void setAge(int age) {
this.age = age;
}
//Dog类和Cat类公共的方法
public void eat() {
System.out.println(name + "吃饭");
}
}
子类: Dog
//子类
public class Dog extends Animal {
//这里的colour就是子类与父类不同名的成员变量
public String colour;
//子类Dog独有的方法
public void dogCall(){
//将从父类继承的name属性赋值
String name = "小黄";
//通过getAge访问父类的私有属性age
System.out.println(name + getAge() + "汪汪汪");
}
}
入口函数
public class Demo {
public static void main(String[] args) {
//通过New关键字进行创建dog对象
Dog dog = new Dog();
//通过子类对象访问父类的私有属性age并进行赋值
dog.setAge(1);
//通过对象dog调用子类方法
dog.dogCall(); // 小黄1汪汪汪
}
}
访问父类与子类同名的成员变量
父类
//父类
public class Animal {
String name = "小黄";
//Dog类和Cat类公共的方法
public void eat() {
System.out.println(name + "吃饭");
}
}
子类
//子类
public class Dog extends Animal {
//子类Dog独有的方法
public void dogCall() {
//将从父类继承的name属性赋值
String name = "小黄";
System.out.println(name + "汪汪汪");
}
}
入口函数
//启动项
public class Demo {
public static void main(String[] args) {
//通过New关键字进行创建dog对象
Dog dog = new Dog();
//通过对象dog调用子类方法
dog.dogCall(); // 阿福汪汪汪
}
}
父类中有属性名为name,子类中也有属性名name,且他们的类型相同,我们通过打印可以看到打印输出的为子类name成员变量的值
在子类成员方法中或者通过子类成员对象访问成员变量时:
- 如果访问的成员变量子类有,优先访问子类
- 如果访问的成员变量子类没有,访问从父类继承下来的成员变量,如果父类也没有,则编译报错
- 如果访问的成员变量子类和父类同名,根据就近原则优先访问子类的成员变量
- 也可以通过关键字类访问成员变量(访问子类本类的用this,访问父类的用super)
子类访问父类的成员方法(直接访问)
父类
//父类
public class Animal {
String name = "小黄";
//父类的方法eat()
public void eat() {
System.out.println(name + "吃饭");
}
}
子类
//子类
public class Dog extends Animal {
//子类Dog独有的方法dogCall()
public void dogCall(){
//将父类的方法一起添加进来,方便调用
eat();
//将从父类继承的name属性赋值
String name = "小黄";
System.out.println(name + "汪汪汪");
}
}
入口函数
//启动项
public class Demo {
public static void main(String[] args) {
//通过New关键字进行创建dog对象
Dog dog = new Dog();
//通过对象dog调用子类方法
dog.dogCall(); // 小黄吃饭 小黄汪汪汪
}
}
访问父类与子类中同名的方法(优先访问子类)
父类
//父类
public class Animal {
String name = "小黄";
//父类的方法eat()
public void eat() {
System.out.println(name + "吃饭");
}
}
子类
//子类
public class Dog extends Animal {
//子类Dog的方法eat()
public void eat(){
//将父类的方法一起添加进来,方便调用
//将从父类继承的name属性赋值
String name = "小黄";
System.out.println(name + "汪汪汪");
}
}
程序入口函数
//启动项
public class Demo {
public static void main(String[] args) {
//通过New关键字进行创建dog对象
Dog dog = new Dog();
//通过对象dog调用子类方法
dog.eat(); // 小黄汪汪汪
}
}
如果父类和子类的成员变量和成员方法相同,访问时优先级肯定时子类更高,如何通过子类的方法去访问父类的成员变量或者方法?
super 关键字 🔞
💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤
super.成员变量:表示访问父类的成员变量
super.成员方法: 表示访问父类的成员方法
super(): 表示访问父类的构造方法
super关键字只能在非静态方法中使用 ⭕
💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤💤
super关键字:在子类中访问父类的成员方法或者变量
父类
//父类
public class Animal {
String name = "大黄";
//父类的方法eat()
public void eat() {
System.out.println(name + "吃饭");
}
}
子类 使用super调用父类的方法
//子类
public class Dog extends Animal {
//子类Dog的方法eat()
public void eat(){
//将从父类继承的name属性赋值
String name = "小黄";
//利用super关键字访问父类中同名的成员变量name
System.out.println(super.name + "汪汪汪");
}
}
启动项
public class DemoApplication {
public static void main(String[] args) {
//通过New关键字进行创建dog对象
Dog dog = new Dog();
//通过对象dog调用子类方法
dog.eat(); // 子类中使用super调用父类name,打印结果: 大黄汪汪汪
}
}
子类构造器 🈲
子类之所以叫子类,因为它继承了父类,但子类是不继承父类的构造器的,他只是进行一个调用
* 如果父类的构造器没有参数,则子类的构造器不需要使用super关键字调用父类的构造器,系统会自动调用父类的无参构造
* 如果父类的构造器带有参数,则必须在子类构造器中通过super关键字调用父类构造器并赋予相应的形参列表
* super(实参列表)必须在构造器的第一行
//父类
public class Animal {
private int age;
//父类的无参构造
public Animal() {
System.out.println("Animal()的无参构造");
}
//父类的有参构造
public Animal(int age) {
System.out.println("Animal()的有参构造");
this.age = age;
}
}
Dog类:利用super调用父类中的有参构造器
//子类
public class Dog extends Animal {
private int age;
//自动调用父类的无参构造
public Dog() {
System.out.println("Dog的无参构造");
}
public Dog(int age) {
//利用super调用父类中的有参构造器
super(200);
System.out.println("Dog的有参构造"+age);
this.age = age;
}
}
Cat类:利用super调用父类中的有参构造器
//Cat类通过extends关键字继承父类Animal
public class Cat extends Animal {
private int age;
//调用的无参构造
public Cat() {
System.out.println("Cat的无参构造");
}
public Cat(int age) {
//利用super调用父类中的有参构造
super(100);
System.out.println("Cat的有参构造"+age);
this.age = age;
}
}
入口函数
public class DemoApplication {
public static void main(String[] args) {
System.out.println("Dog类继承-----------");
Dog dog = new Dog();
Dog dog1 = new Dog(300);
System.out.println("Cat类继承------------");
Cat cat = new Cat();
new Cat(400);
}
}
输出
Dog类继承-----------
Animal()的无参构造
Dog的无参构造
Animal()的有参构造
Dog的有参构造300
Cat类继承------------
Animal()的无参构造
Cat的无参构造
Animal()的有参构造
Cat的有参构造400