java的继承和多态

1.继承语法

1.语法的定义

继承 (inheritance) 机制 :是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保
持原有类特 性 的基础上进行扩展,增加新功能 ,这样产生新的类,称 派生类 。继承呈现了面向对
象程序设计的层次结构, 体现了 由简单到复杂的认知过程。继承主要解决的问题是:共性的抽
取,实现代码复用 。下面我举个people和student的例子:
class peopel{
    public String name;
    public int age;
    public peopel(String name){//父类构造方法
        this.name=name;
        System.out.println("name:"+name);
    }
    public void study(){
        System.out.println(name+"在学习");
    }
}
class student extends peopel{
    public student(String name) {
        super(name);//对父类的成员进行初始化
    }
    public void study(){
        System.out.println(name+"在看书");//成员方法的重写
    }
}

这段代码中父类为people,子类为student,在引用子类时,会调用父类中的成员,避免了在不同类中书写相同成员的情况。

继承的格式如下:

2.子类访问父类成员方法

1)成员方法名不相同

public class test1 {
    public void methodA(){
        System.out.println("父类的中的methodA");
    }
}
class son extends test1{
    public void methodB(){
        System.out.println("子类中的methodB");
    }
    public void methodA(){//与父类中的成员方法名相同
        System.out.println("子类中的methodA");
    }
}
class c{
    public static void main(String[] args) {
        son x = new son();
        x.methodA();
        x.methodB();
    }
}

运行结果:

由上述代码和结果不难看出,在成员方法名不同时,遵循着就近原则

2)成员方法名相同

我们对上一段代码做一些修改:

public class test1 {
    public int num;
    public void methodA(){
        System.out.println("父类的中的methodA");
    }
    public void methodC(int num){
        this.num=num;
        System.out.println("父类中的methodC");
    }
}
class son extends test1{
    public void methodB(){
        System.out.println("子类中的methodB");
    }
    public void methodA(){//与父类中的成员方法名相同
        System.out.println("子类中的methodA");
    }
    public void methodC(){
        System.out.println("子类中的methodC");//与父类中的成员方法名相同
    }
}
class c{
    public static void main(String[] args) {
        son x = new son();
        x.methodA();
        x.methodB();
        x.methodC();//子类中的是无参成员方法
        x.methodC(10);//此处含有参数,所以调用的是父类
    }
}

运行结果:

不出所料,在成员方法名相同时一样遵循了就近原则,但不同的是,当方法名相同而参数列表不同

时,子类的同名方法是不会把父类的方法取代的,如代码中的methodC和methodC(10)。

小总结:

  • 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中
  • 找,找到 则访问,否则编译报错。
  • 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同 (
    ) ,根据调用 方法适传递的参数选择合适的方法访问,如果没有则报错;

3.继承关系上的执行顺序

​
​
class person{
    public String name;
    public int age;
    public person(String name,int age){
        this.age=age;
        this.name=name;
        System.out.println("父类的构造方法执行");
    }
    {
        System.out.println("父类实例代码块执行");
    }
    static{
        System.out.println("父类静态执行");
    }

        //static {
            //System.out.println("子类静态执行");
       // }

}
class son1 extends person {
    public son1(String name, int age) {
        super(name, age);
        System.out.println("子类的构造方法执行");
    }

    {
        System.out.println("子类实例代码块执行");
    }

    static {
        System.out.println("子类静态执行");
    }
}

    public class test2 {
        public static void main(String[] args) {
          son1 c = new son1("zhangsan",20); 
          person b = new person("xiaoming",15);
            
        }
    }

​

​

根据代码显而易见,父类永远大于子类,静态代码大于实例代码块大于构造代码块

结论:

  • 父类静态代码块优先于子类静态代码块执行,且是最早执行。
  • 父类实例代码块和父类构造方法紧接着执行。
  • 子类的实例代码块和子类构造方法紧接着再执行
  • 第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

2.super关键字

产生原因:由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在

子类方法中访问父类同名成 员时,该如何操作?直接访问是无法做到的,Java提供了super关键

字,该关键字主要作用:在子类方法中访问父 类的成员

值得注意的是:super关键字只能在非静态方法中使用。

1)当父类含有无参构造方法的情况

class father{
    public father(){//无参构造方法
        System.out.println("无参的执行");
    }
}
class son2 extends father{
    public son2(){
        System.out.println("子类的执行");
    }
}
public class test3 {
    public static void main(String[] args) {
        son2 a = new son2();
    }
}

结果:

子类构造方法中会默认调用父类的无参构造方法,用户没有写时,编译器会自动添加,而且super()

必须是子类构造方法中第一条语句, 并且只能出现一次。

2.super.成员/方法和super(成员)的作用

我们先用一段代码来稍微体会一下这两者的区别

class Baba{
    public int age=10;
    public String name="lihua";
    public Baba(String name,int age){
        this.age=age;
        this.name=name;
    }
    public void fun(){
        System.out.println("父类成员方法");
    }
}
class erzi extends Baba{
    //int age = 100;
    public erzi(String name,int age){
        super(name,age);//在子类中对父类的成员进行初始化
    }
    public void fun1(){
        System.out.println("子类成员方法");
    }
    public void fun2(){
        System.out.println("用super调用父类");
        super.fun();
    }
    public void fun3(){
        age=15;
        name="zw";
        super.age=10;
        super.name="lihua";
        System.out.println(name+age);
    }
}
public class test4 {
    //public static void
    public static void main(String[] args) {
        erzi a = new erzi("xiaoming",100);
        System.out.println(a.age);
        System.out.println(a.name);
        a.fun1();
        a.fun2();
        a.fun3();
    }
}

结果:

看过代码后不难知道,子类在继承父类之后,如果需要调用父类中的成员,就要利用super(成员

变量)来将父类的成员初始化,否则将报错。而super.成员/方法则是直接调用,调用时需要在子类

的方法中,而不能自己自成一条语句。

3.final关键字

final 关键可以用来修饰变量、成员方法以及类。
作用:被final修饰后,表示此类无法继承
显而易见,继承之后报错了。

4.多态

多态的概念:通俗来说,就是多种形态, 具体点就是去完成某个行为,当不同的对象去完成时会产
生出不同 的状 态。拿榨汁机举个例子,当放进不同水果时,出来的果汁就不同,当榨汁的过程是
相同的,就是说在对象不同时,就会产生不同的结果。

1.基础实现

1)条件:必须在继承体系下

                子类必须要对父类中方法进行重写

                通过父类的引用调用重写的方法

接下来拿狗和猫做一个具体实现:

public class Animal {
    String name;
    int age;
    public Animal(String name,int age){
        this.age=age;
        this.name=name;
    }
    public void eat(){
        System.out.println(name+"在吃");
    }
}
class Dog extends Animal{
    public Dog(String name,int age){
        super(name,age);
    }
    public void eat(){
        System.out.println(name+"在吃肉");
    }
}
class Cat extends Animal{
    public Cat(String name,int age){
        super(name,age);
    }
    public void eat(){
        System.out.println(name+"在吃🐟");
    }
}
class test{
    public static void eat(Animal a){
        a.eat();
    }
    public static void main(String[] args) {
        Cat m = new Cat("五月",3);
        Dog g = new Dog("大黄",4);
        m.eat();
        g.eat();
        eat(m);
        eat(g);
    }
}

输出结果:

2.重写与重载

重写是子类对父类 非静态、非private修饰,非final修饰,非构造方法 等的实现过程进行重新编写,
返回值和形参都不能改变 即外壳不变,核心重写! 重写的好处在于子类可以根要,定义特定于自
己的行为。 也就是说子类能够根据需要实现父类的方法。
如上述动物代码中猫和狗对eat的改变就属于重写。
重写与重载的区别
即:方法重载是一个类的多态性表现 , 而方法重写是子类与父类的一种多态性表现。

3.向上转型和向下转型(重点)

1)向上转型的概念和写法

向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。
语法格式:父类类型 对象名= new 子类类型 ()

2)向上转型的两种方法

方法一:子类直接赋值给父类

方法二:方法传参:形参为父类型引用,可以接收任意子类的对象

public class person {
    String name;
    int age;
    public person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void life(){
        System.out.println(name+"生活了"+age+"年");
    }
    public void study(){
        System.out.println(name+"上学");
    }
}
class student1 extends person{
    public student1(String name,int age){
        super(name, age);
    }
    public void study(){
        System.out.println(name+"读书");
    }
}
class student2 extends person{
    public student2(String name,int age){
        super(name, age);
    }
    public void study(){
        System.out.println(name+"写作业");
    }
    public void sport(){
        System.out.println(name+"打球");
    }
}
class test2{
    public static void study(person a){//方法二:方法传参:形参为父类型引用,可以接收任意子类的对象
        a.study();
    }
    public static void main(String[] args) {
        person a = new student1("lihua",18);//方法一:子类直接赋值给父类
        person b = new student2("xiaoming",17);
        //student1 c = new student1("xiaohong",16);
        a.study();
        b.study();
        student2 c = new student2("zhangsan",20);
        c.sport();
    }
}

上述代码体现了向上转型的两种方法,其中有个现象:向上转型后无法调用到子类特有的成员方法。

如b对象为向上转型,在输入b.时,提示栏没有student2特有的sport成员方法。

而c对象不为向上转型,在输入c.时,提示栏就出现了sport方法。

3)向下转型

本质:一个已经向上转型的子类对象,将父类引用转为子类引用。

特点:

  • 要求父类的引用必须指向的是当前目标类型的对象
  • 只能强制转换父类的引用,不能强制转换父类的对象
  • 当向下转型后,可以调用子类类型中所有的成员
class test4{
    public static void fun(father a){
        a.fun();
    }
    public static void main(String[] args) {
        father a = new son("lihua",12);
        son b = (son) a;
        a.fun();
        b.fun2();
        ((son) a).fun2();
    }
}

在没有向下转型之前a对象中无法引用fun2方法,而向下转型之后就可以了

4.多态数组

class test3{
    public static void teach(teacher a){
        a.teach();
    }
    public static void main(String[] args) {
        teacher[] teacher1 = new teacher[4];
        teacher1[0]=new teacher("lihua",25);//此处的数组名为前面定义的对象
        teacher1[1]=new english("xm",26);
        teacher1[2]=new math("xh",24);
        teacher1[3]=new sport("xk",28);
        for (int i=0;i<teacher1.length;i++){
            teacher1[i].teach();
            //teach(teacher1[i]);
        }
    }
}

多态数组:数组的定义类型为父类类型,里面保存的实际元素类型为子类类型。
代码示例:(循环调用基类对象,访问不同派生类的方法

此次继承和多态的分享就到这了!谢谢观看!!

如有建议和意见欢迎的评论区交流!!!

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值