day10 Java 面向对象 继承 super 重写


看着他们的表情,那满足的模样
看着他们快乐,我也跟着饱了




一、继承

书写代码时,经常发现两个或多个类,在成员变量和成员方法上高度的一致,仅仅有一小部分不同。此时,为了实现两个类,再花费大量时间用来书写重复代码,就很浪费时间。
针对这种情况,Java 给出了一种规则,来规避重复 —— 继承

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中
那么多个类无需再定义这些属性和行为,只要继承那个类即可

1、如何实现及特点

代码格式

//创建一个 Pokemon 类
class Pokemon{
    private String name;
    private int level;
    private final int skillsQuantity = 4;
}
//创建一个 Pokemon 的派生类 Gardevoir类
class Gardevoir extends Pokemon{
}        

继承的特点
1、Java 只允许单继承,不允许多继承(一个派生类拥有多个父类)
2、Java 允许多级继承(B继承A,C继承B)

继承的优势
1、提高代码的复用性
2、提高了代码的维护性
3、让类与类之间产生了关系,是多态的前提,为后面讲解多态做准备

继承的劣势
继承让类与类产生了关系,提高的代码的耦合性

耦合:类与类之间的关系
内聚:就是类自己完成某件事的能力

开发的原则:
低耦合,高内聚

2、注意事项

1、派生类只能继承父类内的非私有成员(变量和方法)
2、构造方法不能被继承,但是可以利用关键字 super 来调用父类的构建方法
3、尽量不要为了小部分功能而使用继承

3、继承与成员变量的关系

当父类和派生类拥有同样变量名的变量时,在调用时依然遵循就近原则
派生类中访问变量的顺序:
1、首先在派生类的局部变量中找,有就返回
2、接着在派生类的成员变量中找,有就返回
3、最后在父类的成员变量中找,有就返回
4、若以上区域内都没有,则会因访问不到变量而报错
(不会找到父类的局部变量区,因为没有调用方法,所以此时不存在这些变量)

4、继承与成员方法的关系

派生类中调用方法的顺序:
1、首先在派生类中查找,有就调用
2、接着在父类中查找,有就调用
3、若以上区域都没有,则会因为调用不到方法而报错



二、super 关键字

派生类只能访问自己重新定义的,同父类同名的变量,那该如何访问父类中原本的同名变量呢。Java 提供了一个关键字来处理这种情况 —— this

1、基本定义

作用:代替父类对象,访问父类数据
使用方法
super . 父类成员

2、和 this 区别

this 代表的是当前对象的引用
super 代表是父类存储空间的引用


3、使用方法

3.1 调用成员

this . 成员变量/方法
调用的是本类中的成员变量/方法
super . 成员变量/方法
调用的是父类的成员变量/方法

3.2 访问构造方法
this(…)
调用本类中构造方法
super(…)
调用父类中构造方法



三、继承中的构造方法

在继承中,派生类并不会继承父类的构造方法
(个人认为是因为派生类和父类是不同的两个类,不需要额外继承构造方法)
但是在创建子类对象之前,会先访问一遍父类的构造方法,用来完成初始化

class Pokemon{
    Pokemon(){
        System.out.println("Pokemon无参构造方法");
    }
}

class PokemonPearl extends Pokemon{
    PokemonPearl(){
        System.out.println("PokemonPearl无参构造方法");
    }
}

public class StractureTest {
    public static void main(String[] args) {
        PokemonPearl gardevoir = new PokemonPearl();
    }
}

请添加图片描述

1、父类未提供无参构造方法

上面说派生类在创建对象时会先访问父类的无参构造方法,那么若父类没有定义无参构造方法,就会造成无法使用派生类的结果。那么该如何解决

1、在父类中加一个无参构造
2、使用super关键字去调用父类中带参数的构造方法 super("…")
3、子类通过调用本类其他的构造方法
     使用this关键字间接的调用super去访问父类的构造方法

要想初始化子类,就必须先初始化父类(也就是调用父类的构造方法)

//方法二
class Pokemon{
    String name;
    Pokemon(String name){
        System.out.println("Pokemon无参构造方法");
    }
}

class PokemonPearl extends Pokemon{
    PokemonPearl(){
    	super("不填或随意填");   //调用父类含参构造方法
        System.out.println("PokemonPearl无参构造方法");
    }
}

//方法三
class Pokemon{
    String name;
    Pokemon(String name){
        System.out.println("Pokemon无参构造方法");
    }
}

class PokemonPearl extends Pokemon{
    PokemonPearl(){
    	this("不填或随意填");     //调用自己的含参构造方法
        System.out.println("PokemonPearl无参构造方法");
    }

	PokemonPearl(String name){
		super("不填或随意填")    //再调用父类含参构造方法
		System.out.println("PokemonPearl含参构造方法");
	}
}

方法三的输出结果
请添加图片描述

2、注意事项

super(…)和this(…)必须出现在构造方法的第一条语句上
在Java中不允许对一个进行多次初始化,每个类只能初始化一次



四、重写

方法的重写:
子类中出现了和父类中一模一样的方法声明,叫做重写,也叫覆盖、复写

方法的重载:
本类中出现了方法名一样,参数列表不一样的方法,与返回值无关的方法,叫重载

注意事项

1、方法的重写,出现在继承中或者后面的实现
2、父类的方法被private修饰不能被重写,甚至算不上重写
    (子类重写父类方法时,访问权限要么和父类方法的访问权限一样,要么比它大)
3、父类若是静态方法,子类也必须通过静态方法进行重写
    (本质不是重写,但是操作类似)



五、练习

//看程序写结果
class Fu{
    public int num = 10;
    public Fu(){
        System.out.print("fu");
    }
}
class Zi extends Fu{
    public int num = 20;
    public Zi(){
        System.out.print("zi");
    }
    public void show(){
        int num = 30;
        System.out.print(num);
        System.out.print(this.num);
        System.out.print(super.num);
    }
}
class ExtendsTest {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}        

fu zi 30 20 10

//看程序写结果
class Fu1 {
    static {
        System.out.println("静态代码块Fu"); // 1
    }

    {
        System.out.println("构造代码块Fu");// 2
    }

    public Fu1() {
        System.out.println("构造方法Fu");// 3
    }
}

class Zi1 extends Fu1 {
    static {
        System.out.println("静态代码块Zi");// 4
    }

    {
        System.out.println("构造代码块Zi");// 5
    }

    public Zi1() {
        System.out.println("构造方法Zi");// 6
    }
}

public class ExtendsTest2 {
    public static void main(String[] args) {
        Zi1 z = new Zi1();
    }
}

1 4 2 3 5 6
1、静态的内容是随着类的加载而加载的,静态代码块里面的内容会优先执行
2、静态代码块 > 构造代码块 > 构造方法
3、子类初始化之前会先对父类进行初始化

//看程序写结果
class X {
    Y b = new Y();
    X() {
        System.out.print("X");
    }
}
class Y {
    Y() {
        System.out.print("Y");
    }
}
public class Z extends X {
    Y y = new Y();
    Z() {
//        super();
        System.out.print("Z");
    }
    public static void main(String[] args) {
        new Z();
    }
}

Y X Y Z
每次初始化父类时,只需要初始化一次



总结

派生类只能继承父类内的非私有成员(变量和方法)

构造方法不能被继承,但是可以利用关键字 super 来调用父类的构建方法

this 代表的是当前对象的引用

super 代表是父类存储空间的引用

重写(Override) 派生类中出现和父类同方法名,参数列表的方法

重载(Overload) 同一类中,出现同方法名,不同参数列表的方法

父类可以被强制转换成子类,但是不能使用子类特有的方法和属性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值