目录
1.理解继承
什么是继承呐?我们先看一下图片:
图片反映了教师和学生都属于人这一类,他们也有自己的共性。
任课教师和教辅人员都属于教师,也同时都属于人这一类;
本科生和研究生都属于学生,也同时都属于人这一类。
就好比教师是任课教师和教辅人员的父类,学生是本科生和研究生的父类。而教师和学生属于人的子类。
父类通用,子类具体。子类具有父类的一般特征也具有自身特性。
强调:共性抽取,实现代码复用,这就是继承的目的。
2.继承的语法格式
关键字extends 继承的语法格式也很简单:
修饰符 class 子类(派生类) extends 父类(基类/超类){
//
}
下面我们来实现一下 共性抽取,写出派生类。
/**
* @author Sun
* @version 2021.2
* @date 2022/5/19 11:20
*/
class Person {
public String name;
public int age;
public void school() {
System.out.println(name+"正在学校!");
}
}
class Student extends Person {
public int studentid;
public void study() {
System.out.println("我是学生,我在学习!");
}
}
class Teacher extends Person {
public int workid;
public void teach() {
System.out.println("我是老师,我在备课!");
}
}
强调:
(1)子类继承父类,会将父类的成员方法或成员变量都继承到自己身上;
(2)子类继承父类,子类必须新添加自己特有的成员,体现出和父类的相同,不然子类和父类相同了,那要继承就没有意义。
3.子类对父类的访问
问题:
🐲(1)在子类中,如何访问父类的成员变量
🐲(2)在子类中,如何访问父类的成员方法
3.1子类中访问父类的成员变量
子类和父类没有同名的成员变量(直接访问)
这种访问,非常简单:
package 继承;
/**
* @author Sun
* @version 2021.2
* @date 2022/5/19 11:37
*/
class Father {
public int a=1;
public int b=2;
}
class child extends Father {
public int c=3;
public int d=4;
public void test() {
System.out.println(this.a);
System.out.println(this.b);
System.out.println(this.c);
System.out.println(this.d);
}
}
public class Test {
public static void main(String[] args) {
child child = new child();
child.test();
}
}
this.成员变量
子类和父类有同名的成员变量(super关键字)
相信大家也已经看明白了,如果子类非要访问父类同名成员,那就得使用super关键字
super关键字表示子类从父类中继承的这一部分成员的地址
总结: 子类访问父类成员变量
🟥(1)如果子类中有,优先访问自己的成员变量
🟩(2)如果子类中没有,就从父类中继承下来,如果父类中也没有,那就报错了
🟧(3)如果有成员变量同名,那就优先访问子类自己的
一句话,那就是:
🟪成员变量访问遵循就近原则,先访问自己,如果没有,找父类
3.2子类中访问父类的成员方法
子类和父类成员方法名不同(直接调用)
class Base{
public int a=1;
public int b=2;
public void methodA() {
System.out.println("Base::methodA()");
}
}
class Derived extends Base {
public int a=3;
public int d=4;
public void methodB() {
System.out.println("Derived::methodB()");
}
public void test(){
methodA();//访问父类继承的methodA()
methodB();//访问字类自己的methodB()
}
}
public class Test02 {
public static void main(String[] args) {
Derived derived = new Derived();
derived.test();
}
}
成员方法名相同子类和父类(super关键字)
package 继承;
/**
* @author Sun
* @version 2021.2
* @date 2022/5/19 11:53
*/
class Base{
public int a=1;
public int b=2;
public void methodA() {
System.out.println("Base::methodA()");
}
public void methodB() {
System.out.println("Base::methodB()");
}
}
class Derived extends Base {
public int a=3;
public int d=4;
public void methodA(int val) {
System.out.println("Derived::methodA(int)"+val);
}
public void methodB() {
System.out.println("Derived::methodB()");
}
public void test(){
methodA();//Base::methodA()
methodA(100);//Derived::methodA(int)
methodB();//Derived::methodB(int)
}
}
public class TestDemo {
public static void main(String[] args) {
Derived derived = new Derived();
derived.test();
}
}
通过代码,我们可以看出:
如果子类和父类的同名方法中,构成了重载,也就是同名但参数列表不同时,就可以根据自己的参数用合适的方法进行访问
如果子类方法和父类同名方法中,没有构成重载,那就是重写。就还是优先访问子类自己的方法。
如果非要访问父类的同名成员方法, super.同名方法 就可以实现了。
package 继承;
/**
* @author Sun
* @version 2021.2
* @date 2022/5/19 11:53
*/
class Base{
public int a=1;
public int b=2;
public void methodA() {
System.out.println("Base::methodA()");
}
public void methodB() {
System.out.println("Base::methodB()");
}
}
class Derived extends Base {
public int a=3;
public int d=4;
public void methodA(int val) {
System.out.println("Derived::methodA(int)"+val);
}
public void methodB() {
System.out.println("Derived::methodB()");
}
public void test(){
methodA();//Base::methodA()
methodA(100);//Derived::methodA(int)
super.methodB();//Base::methodB()
}
}
public class TestDemo {
public static void main(String[] args) {
Derived derived = new Derived();
derived.test();
}
}
总结:
(1) 如果自雷中有,优先访问自己的成员方法
(2)如果子类中没有,就从父类中继承;如果父类中也没有,那就报错
(3) 如果有成员方法同名,并构成重载,就可以根据自己的参数,选择合适的方法访问
(4) 如果有成员方法同名,但没有构成重载,如果直接访问成员方法就会访问子类自己的
(5) 如果有成员方法同名,但有没构成重载,那就直接 super.同名方法 ,才可以访问父类成员方法
成员变量访问原则 : 先自己,自己没有,找父类。
4.super关键字
前面我们已经使用了super关键字了,下面我们来了解一下super的其他作用:
作用:在子类方法中访问父类的成员
super关键字只能在非静态的方法中使用:
Because : 静态方法 不依赖对象
super 从父类中访问成员对象
两个矛盾,不能同时存在。
super() 调用父类的构造方法
来初始化子类继承过来父类的属性。
5.super和this的异同点
相同点 |
(1)在构造方法中调用,必须是构造方法中的的语句,并且super和this不能同时存在 (2)只能在静态方法中使用,两个都需要对象 (3)都是关键字 |
不同点 |
(1)this是当前对象的引用,super是子类对象从父类继承下来的成员的引用 (2)在构造方法中一定会存在super()的调用,不管写不写都有,this()是如果不写就没有 (3) this()用于调用自己类的构造方法 super()用于调用父类的构造方法,两个不能同时使用 (4) 在静态的成员方法中,this是用来访问本类的方法和属性,super用来访问从父类继承下来的属性 |
6.子类对象的构造方法
子类对象的构造方法就是由父类继承下来的构造方法+子类构造方法中添加的部分组成。
写一个子类对象的构造方法:
class Animal{
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name+"正在吃饭!");
}
}
class Dog extends Animal {
public float weight;
public Dog(String name,int age,float weight) {
super(name, age);
//调用父类的构造函数,来初始化此时子类继承过来父类的属性
this.weight = weight;
}
public void bark() {
System.out.println(name+"正在狗叫");
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", weight=" + weight +
'}';
}
}
}
🟧子类对象构造时,需要先调用父类构造方法,将从父类继承下来的成员构造完整,
然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整。
⚜️提几点注意:
🤠(1)如果父类执行默认的构造方法,那么在子类构造方法的第一行默认含有super()的调用
🤠(2)如果父类构造方法是带有参数的,此时编译器给子类不会执行默认的构造方法,
这就要程序员自己给子类定义构造方法了
🤠(3)在子类构造方法中,super()调用父类构造时,必须是子类构造方法中第一条语句。
🤠(4)super()只能在子类构造方法中出现一次,并且不能和this同时出现
7.在继承中代码块的执行顺序(重点:静态优先,由父及子)
class Animal{
public String name;
public int age;
static {
System.out.println("Animal的静态代码块!");
}
{
System.out.println("Animal的实例代码块!");
}
public Animal() {
System.out.println("Animal不带参数的构造方法!");
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name+"正在吃饭!");
}
}
class Dog extends Animal {
public float weight;
static {
System.out.println("Dog的静态代码块!");
}
{
System.out.println("Dog的实例代码块!");
}
public Dog() {
System.out.println("Dog的不带参数的构造方法!");
}
public Dog(String name, int age, float weight) {
super(name, age);
this.weight = weight;
}
public void bark() {
System.out.println(name+"正在狗叫");
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", weight=" + weight +
'}';
}
}
}
public class Test01 {
public static void main(String[] args) {
Dog dog = new Dog();
}
}
大家可以看看执行后的结果:
是不是验证了 ——静态优先,由父及子
父类和子类对的静态方法——父类的实例和构造方法——子类的实例和构造方法
而且需要注意的是 静态代码块只执行一次。
8.访问限定符protected(受保护的)
范围 |
private 私有 |
default 默认 |
protected 继承 |
public 公开 |
---|---|---|---|---|
同一包中的同一类 | ✓ | ✓ | ✓ | ✓ |
同一包中的不同类 | ✓ | ✓ | ✓ | |
不同包中的子类 | ✓ | ✓ | ||
不同包中的非子类 | ✓ |
我们可以清楚的看到,protected的访问范围。
9.继承类型
继承类型可以分为以下几个:
(1)单继承
Java中只支持单继承。
(2)多级继承
一层一层的来继承。
(3)分层继承(不同类继承同一个类)
10.关键字final
(1)final修饰成员变量时,变量就不能在修改并且属于常量。
(2)final修饰类时,此类不能被继承。
(3)final修饰方法是,此方法不能被重写。
11.继承和组合的选择
继承 组合 继承指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,而且可以增加它自己的新功能的能力,直接点讲就是
🟪共性抽取,实现代码复用
🟦它的关系就是 is-a
🟩组合是通过对现有对象进行拼装即组合产生新的具有更复杂的功能。
🟦组合体现的是整体与部分,所拥有的关系,也就是has-a的关系
🟪也把这种方式的代码复用叫黑盒式代码复用
拓展:
😁复用性是面向对象的语言好处之一,
😁而这个复用性在java代码中,有三个表现形式:继承,组合,代理。
在两种都可行的情况下,优先使用组合,原因是组合比继承更加灵活,也更有助于代码维护。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/119576.html