Java 继承(上)
Java 继承 (上)
文章目录
- Java 继承 (上)
- 1. 为什么需要继承
- 2. 继承的概念
- 3. 继承的语法
- 4.父类成员在子类中的访问
- 4.1 子类中访问父类的成员变量
- 4.1.1 子类和父类不存在同名的成员变量
- 4.1.2 子类和父类存在同名的成员变量
- 4.1.3 子类中访问父类的成员变量总结:
- 4.2 子类中访问父类的成员方法
- 4.2.1 子类和父类不存在相同的成员方法
- 4.2.2 子类和父类存在相同的成员方法
- 4.2.3 子类中访问父类的成员方法总结:
- 4.3 本知识点的总结:
- 5. super关键字
- super 关键字的简单演示
- super 关键字的用法
- super 关键字的注意事项
- 6. 总结:
观前提醒:如果你没学完 Java类和对象 的基础知识,或者没有看过我写的 JAVA 初识类和对象(上)这篇博客,需要你先进去我的主页,认真学习完这篇博客了,再过来看 Java继承(上)
本节目标:
- 为什么需要继承
- 了解什么是继承(继承的概念)
- 如何实现继承(继承的语法)
- 父类的成员在子类中的访问
- 认识 super关键字 和 了解 super关键字的作用
1. 为什么需要继承
为了更好的引出继承的概念,我们先写几个代码给大家看看:
写一个 Dog 类,写一个 Cat 类,再写一个 Test类,Test类内,创建main方法,用来实例化 Dog 和 Cat类,同时,调用 Dog 和 Cat类的方法。
Dog类:
public class Dog {private String name;private int age;public Dog(String name, int age) {this.name = name;this.age = age;}public void sleep() {System.out.println(this.name+"正在睡觉...");}public void eat() {System.out.println(this.name+"正在吃饭...");}public void bark() {System.out.println(this.name+"正在汪汪叫...");}
}
Cat类:
public class Cat {private String name;private int age;public Cat(String name, int age) {this.name = name;this.age = age;}public void sleep() {System.out.println(this.name+"正在睡觉...");}public void eat() {System.out.println(this.name+"正在吃饭...");}public void mimi() {System.out.println(this.name+"正在咪咪叫...");}
}
Test类:
public class Test {public static void main(String[] args) {Dog dog = new Dog("旺财",10);dog.bark();dog.sleep();dog.eat();Cat cat = new Cat("小虎",6);cat.mimi();cat.sleep();cat.eat();}
}
运行结果:
根据运行结果,可以知道,Test类内,实例化了 Dog 和 Cat 类,并利用对象的引用,成功调用了 Dog类内的方法,Cat类内的方法。
但是,通过观察可以发现,Dog类和Cat类的代码里面,有着可优化的地方,那就是,这两个类里面,重复的代码太多了!!!
那么有没有办法,把这些重复的这段代码给提取出来,单独放到一块呢?
有!需要使用到继承的设计思想。
那,什么是继承???
对每个类的共性(重复的代码)进行抽取,这样的设计思想,我们就把他称之为 “继承”!!!
2. 继承的概念
什么叫做"继承"? 继承在现实生活中的意思和代码中的"继承",其实意思是差不多的,我们可以用现实生活中,儿子继承了父亲的财产一样,来理解继承。
继承:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类(也叫做子类)。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态(后序讲)。
继承是多态实现的基本,没有继承,就没有多态的产生,所以,一定要学好继承,才能够理解并实现多态!!!
注意:继承 或者是后面介绍到的多态,并不是只有 Java 才有的设计思想,而是 面向对象的语言,都有的设计思想,例如:C++,Python 这种可以面向对象的语言,均有继承和多态的概念,只不过不同的语言,实现继承和多态的方法略有不同而已。
例如:狗和猫都是动物,那么我们就可以将共性的内容(重复的代码)进行抽取,采用继承的思想来达到代码的共用。
可以用这样一张图来演示一下:
这样一张图,可以清楚的体现了继承的设计思想,那么,如果Dog类和Cat类想要获取那部分重复的代码来用,该如何获取呢?也就是说,该如何实现继承呢?
3. 继承的语法
在Java当中,如果要实现类与类之间的继承,我们需要使用到 extends 关键字。
继承的语法如下:
public class 子类 extends 父类 {
// …
}
为了后续的演示更加方便,以及不让代码变得复杂,我把上面 Dog类 和 Cat类 中的成员变量的访问修饰限定符,由 private 换成 public ,跟着这个博客去敲代码的时候,记得要换一下!
举个例子吧,我们先创建一个 Animal类,作为 父类,里面存放 Dog类 和 Cat类 中重复的代码:
public class Animal {public String name;public int age;public void sleep() {System.out.println(this.name+"正在睡觉...");}public void eat() {System.out.println(this.name+"正在吃饭...");}
}
public class Dog extends Animal{// ...
}
这段代码中:
Dog类 被称为 子类 或者 派生类,为了更好让大家看的懂,下面提及 子类/派生类 的时候,统一称为子类。
Animal类 被称为 父类 或者 基类,有些书上,甚至由叫 超类,不过,为了大家更好理解这部分知识,下面提及 父类/基类/超类 的时候,统一称为 父类。
这段代码中,我们就说:Dog 这个类 继承了 Animal这个类,Dog这个类,是Animal的子类,Animal这个类,是 Dog这个类的父类。
听着很绕?没关系,我们可以简单理解为:Animal类 是父亲,Dog类 是儿子,就行。
所以,Dog类 和 Animal类 建立继承关系以后,Animal类当中有什么,Dog类当中就同样有什么。
如图所示:
从这张图可以看出,Dog类内,会继承 Animal类 中所有的成员方法和成员变量,即:Animal类中有什么,Dog类中就有什么,而且还可以有除了 Animal类内 其他的成员变量或者成员方法。
注意:
子类继承父类之后,必须要新添加自己特有的成员,体现出与父类的不同,否则这种继承就没有意义了,就如 Dog类 继承 Animal类一样,除了 Animal类中有的,自己还有个 bark() 方法
,体现了与 Animal类的不同。
4.父类成员在子类中的访问
为了更好的演示这块内容,我们需要先创建一个包demo2,然后在dome2包里面,创建三个类,第一个类是 Derived类,这个类,当作子类,第二个类是 Base类,作为父类,第三个类是Test类,里面创建main()方法,用来测试代码的。
至于这三个类里面放什么,根据不同的情况去放不同的内容。
4.1 子类中访问父类的成员变量
分为两种情况:
- 子类和父类不存在同名的成员变量
- 子类和父类存在同名的成员变量
均先展示代码,然后解释。
4.1.1 子类和父类不存在同名的成员变量
public class Base { // 父类public int a = 10;public int b = 20;
}
///
public class Derived extends Base{ // 子类//子类和父类没有相同成员变量的情况public int c = 30;public void printf() {System.out.println("a = "+this.a);//从父类继承下来的成员变量 aSystem.out.println("b = "+this.b);//从父类继承下来的成员变量 bSystem.out.println("c = "+this.c);//访问子类自己的成员变量 c}
}
///
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.printf();}
}
运行结果:
可以看到,当子类中没有和父类有同名的成员变量的时候,使用的是继承下来的和自己有的。
4.1.2 子类和父类存在同名的成员变量
public class Base { // 父类public int a = 10;public int b = 20;
}
///
public class Derived extends Base{ // 子类//子类和父类存在相同成员变量的情况public int c = 30;public int a = 100; // 子类和父类 有相同的成员变量public void printf() {System.out.println("a = "+this.a); // 子类 和 父类 都有这个变量System.out.println("b = "+this.b); // 访问父类中的成员变量 bSystem.out.println("c = "+this.c); // 访问子类自己的成员变量 c}
}
///
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.printf();}
}
运行结果:
从代码的运行结果可以看出,子类和父类成员变量同名,优先使用的是子类的成员变量。
4.1.3 子类中访问父类的成员变量总结:
在子类方法中 或者 通过子类对象访问成员时:
- 如果访问的成员变量子类中有,优先访问自己的成员变量。
- 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类没有定义,则编译报错。
- 如果访问的成员变量与父类中成员变量同名(相同),则优先访问自己的。
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。
4.2 子类中访问父类的成员方法
首先,在这一块我们讲的是,子类中访问父类的成员方法,同样分为两种情况:
- 子类和父类不存在相同的成员方法
- 子类和父类存在相同的成员方法
我们这里讲的是相同的成员方法,而不是相同名字的成员方法。有什么区别呢?
首先,我们来介绍什么是相同的方法:
- 方法名相同
- 形式参数列表相同,包括:形式参数的数据类型,个数,顺序,这三个条件,都要同时满足。
- 返回值不做要求。
所以,如果仅仅只是方法名字相同,并不能满足方法相同,而 4.2.2标题 的内容,需要的是相同的成员方法,才能显示出我们想要的结果。
4.2.1 子类和父类不存在相同的成员方法
public class Base {public void func_A() {System.out.println("这是父类中的func_A方法");}
}
//
public class Derived extends Base {// 子类 和 父类 没有相同成员方法 的情况public void func_B() {System.out.println("这是子类的func_B方法");}public void print_method() {func_A(); // 访问从父类继承下来的方法func_B(); // 访问子类自己的方法}
}
/
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.print_method();}
}
运行结果:
可以看到,当子类中没有和父类中相同的成员方法的时候,使用的是继承下来的和自己有的。
4.2.2 子类和父类存在相同的成员方法
public class Base {public void func_A() {System.out.println("这是父类中的func_A方法");}
}
/
public class Derived extends Base {// 存在 相同成员方法的情况public void func_A() {System.out.println("这是子类中的func_A方法.....");}public void func_B() {System.out.println("这是子类的func_B方法");}public void print_method() {func_A(); // 父类 和 子类 都有这个方法func_B(); // 访问子类自己的方法}
}
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.print_method();}
}
运行结果:
从代码的运行结果可以看出,子类中有父类当中相同的成员方法时,优先使用的是子类的成员方法。
注意!必须是满足方法相同的情况下,只有方法名相同的情况下是不行的。
看下面这张图所演示的,只满足方法同名的情况下:
所以,只有方法名相同的情况下,是不能达到子类和父类中同时有相同的方法,优先使用子类的效果的。
4.2.3 子类中访问父类的成员方法总结:
- 在子类对象中访问父类不相同的成员方法的时候,优先在子类当中去寻找,如果子类当中没有,则去父类当中找,父类找不到的话,就编译报错。
- 在子类对象中访问父类相同的成员方法的时候,优先使用子类的。
4.3 本知识点的总结:
当子类和父类有相同的成员方法或成员变量的时候,优先访问子类的!
遵循就近原则,自己有优先使用自己的,如果没有则向父类中找!
但是,如果在具有相同的成员方法或成员变量的情况下,要在子类方法中访问父类中相同的成员方法或成员变量时,那该怎么办?
答:使用 super 关键字。
5. super关键字
由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的,Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员。
super 关键字的简单演示
接下来,还是看一段代码,代码里面父类和子类有相同的 变量a ,使用 super 关键字在子类中访问 变量a:
public class Base {public int a = 10;
}
//
public class Derived extends Base {int a = 100;public void printf() {System.out.println("同名情况下,访问子类的" + " a = " + this.a);System.out.println("使用 super 关键字,访问父类的" + " a = " + super.a);}
}
//
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.printf();}
}
运行结果:
以 变量 a 为例子,简单使用了一下 super 关键字,
所以,在子类中,如果想要明确访问父类的成员时,借助super关键字即可。
super 关键字的用法
super 关键字 和 this 关键字一样,有三种用法:
- 可以通过 super 访问 当前对象的父类的 成员变量,如:super.变量名
- 可以通过 super 访问 当前对象的父类的 成员方法,如:super.方法名( )
- 可以通过 super 访问 当前对象的父类的 构造方法,如:super( )
第三点用法,在 Java 继承(下) 这篇博客的第一个标题内容【子类的构造方法】中,详细介绍。
super 关键字的注意事项
【注意事项】
- 只能在非静态方法中使用
- 在子类方法中,访问父类的成员变量和方法。
- super 只能指代当前类的父类,不能指代父类的父类,如:super.super.a,这样是错误的!
6. 总结:
由于 Java 继承这部分可讲的东西挺多的,为了避免这篇博客太长了,我将 java 继承部分拆分成 上,下两篇博客。
看到这篇博客的读者,如果需要,可以点击我的头像,进入主页,查看 Java 继承(下)这篇博客,看完这两篇博客,相信你会对Java 继承方面的知识有一个全面的了解,至于需要更深入的了解,则需要你多多练习代码了!
希望这篇文章,可以帮助你对 Java 继承有一个初步的了解,为后面的 java 多态做准备,如果这篇文章内容有错误的,欢迎指出!