Java学习之继承与多态

Java学习之继承与多态

1.继承

1.1 为什么要有继承

我们通过下面的代码进行解释:

class Dog{
    String name;
    int age;
    
    public void eat(){
        System.out.println(name+"正在吃饭");
    }
    
    public void bark(){
        System.out.println(name+"汪汪叫");
    }
}
class Cat{
    string name;
    int age;

    public void eat(){
        System.out.println(name+"正在吃饭");
    }

    public void mew(){
        System.out.println(name+"喵喵叫");
    }
}

通过观察上面的代码,我们发现猫和狗的类存在大量的重复,那能否将这些共性进行抽取呢?面向对象思想中就提到了继承的概念:对共性的抽取,从而实现对代码的复用。

1.2继承的概念

例如猫和狗都是动物,我们则可以将共性的属性进行抽取,从而实现对代码的复用。
在这里插入图片描述
上图中,Dog和Cat类都继承了Animal类,其中Animal类被称为父类、基类或超类,D og和Cat类被称为子类或派生类。继承之后,子类可以复用父类中的成员。

1.3如何实现继承

在Java中要表示继承关系,需要用到extends关键字。

class Animal{
    String name;
    int age;

    public void eat(){
        System.out.println(name+"正在吃饭");
    }

}
class Dog extends Animal{

    public void bark(){

        System.out.println(name+"汪汪叫");
    }
}
class Cat extends Animal{


    public void mew(){

        System.out.println(name+"喵喵叫");
    }
}

public class Text {
    public static void main(String[] args) {
         Dog dog=new Dog();
         Cat cat=new Cat();
         dog.name="七月";
         cat.name="遇见";
         dog.bark();
         cat.mew();
    }
}

在这里插入图片描述
通过运行可以看出,猫和狗这两个类中没有定义任何成员变量,name和age变量一定是从父类中继承下来的。

1.4 super关键字

由于一些原因,子类和父类中会出现相同名称的成员,如果在子类对象中访问父类同名成员时,该如何操作?直接访问是无法做到的,Java中提供了super关键字,该关键字的主要作用:在子类方法中访问父类成员。

class Father{
    int a;
    int b;
    int c;

    public void methodA(){

        System.out.println("父类中无参的methodA");
    }

    public void methodB(){
        System.out.println("父类中的methodB");
    }

}
class Son extends Father{
   int a;
   char c;

    //与父类中的func构成重载
   public void methodA(int a){
       System.out.println("子类中带有参数的methodA");
   }
    //与父类中的func构成重写,重写后序会介绍
    public void methodB(){
        System.out.println("子类中的methodB");
    }
   public void methodC(){
       a=100;
       c='y';
       super.a=101;
       b=105;
       //子类和父类中存在重载的方法,直接可以通过参数列表区分访问父类还是子类的方法
       methodA();//没有参数,调用父类中的methodA()
       methodA(15);//传递int参数,调用子类中的methodA()
       methodB();//直接访问,永远访问的是子类的
       super.methodB();//通过super关键字访问父类成员变量
       System.out.println(a);
       System.out.println(c);
       System.out.println(super.a);
       System.out.println(b);
   }

}

public class Text {
    public static void main(String[] args) {

        Son son=new Son();
        son.methodC();

    }
}

在这里插入图片描述
通过运行结果可以看出,当子类和父类中存在相同的成员变量时,直接访问时,都是访问子类的,如果想要在子类方法中明确访问父类的方法,则有到super关键字即可。

注:
super关键字只能在非静态方法中使用
在子类方法中,访问父类成员变量和方法

2.1再谈构造方法

在类与对象中我们介绍过构造方法,那么在继承中构造方法又是如何使用的呢?
父子父子,先有父再有子,即当我们调用子类构造方法时,得先调用基类构造方法,再执行子类构造方法。

class Base{
    public Base() {

        System.out.println("Base");
    }
}
class Derived extends Base{
      public Derived(){
          //super() 子类构造方法中会默认调用父类的无参构造方法,super()
          //没写时系统会默认加上,且super()必须是子类构造方法的第一条语句
          System.out.println("Derived");
      }
}
public class Text {
    public static void main(String[] args) {
        Derived derived=new Derived();
        
    }

在这里插入图片描述
从运行结果我们可以看出,当我们new一个子类的时候,调用子类构造方法前会先帮助父类进行构造,

注:

  1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构
    造方法
  2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的
    父类构造方法调用,否则编译失败。
  3. 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。
  4. super(…)只能在子类构造方法中出现一次,并且不能和this同时出现

2.2再谈初始化

在类与对象中,我们也提到过初始化的问题,那么在继承关系中,又是怎样的呢。

class Animal {
    String name;
    int age;

    static{
        System.out.println("Animal中的static{}");
    }
    
    {
        System.out.println("Animal中的{}");
    }
    
    public Animal() {
        System.out.println("Animal()");
  }
}
class Dog extends Animal {

    static{
        System.out.println("Dog中的static{}");
    }
    
    {
        System.out.println("Dog中的{}");
    }
    
    public Dog() {
        System.out.println("Dog()");
    }
}

在类与对象中我们提到过代码块这个概念,通过学习我们可以发现,静态代码块是先与构造代码块且只执行一次,即随类的加载而加载,而构造代码块则是先与构造方法的。那么在发生继承的情况下又是如何的呢,通过运行上述代码我们发现:
在这里插入图片描述
静态代码块是最先执行的,然后在执行父类构造代码块和构造方法,最后执行子类的构造代码块和构造方法。

3.多态

多态的概念,通俗来讲,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生不同的形态。

3.1多态的实现

在Java中发生多态必须具备以下条件:

1.向上转型
2.对父类方法进行重写
3.必须在继承体系下

下面,我们通过代码来进行解释:

//多态发生的条件:1.向上转型 2.重写 3.继承
class Animal{
    String name;

    public void eat(){

        System.out.println(name+"正在吃饭");
    }

}
class Dog extends Animal{

     @Override
    public void eat(){   //重写父类方法

         System.out.println(name+"正在吃狗粮");
    }
}
class Bird extends Animal{
      @Override
    public void eat(){

          System.out.println(name+"正在吃鸟粮");
    }
}

public class Text {
    public static void main(String[] args) {
        Animal animal1=new Dog();// 发生向上转型
        //注意,发生向上转型之后,此时通过父类的引用只能访问父类自己的成员,不能访问子类特有的成员
        Animal animal2=new Bird();
        animal1.name="遇见";
        animal2.name="七月";
        animal1.eat();
        animal2.eat();
    }
}

在这里插入图片描述

3.2向上转型和向下转型

3.2.1.向上转型

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

Animal animal=new Cat(“七月”);

向上转型优点:让代码实现更简单灵活
向上转型缺点:无法调用子类特有的方法

3.2.2向下转型

将一个子类对象经过向上转型转化为父类对象后无法调用子类特有的方法,但有时候要调用子类特有的方法,此时,将父类引用还原为子类引用即可,即向下转型。

        Animal animal=new Dog();
        //向下转型
        Dog dog=(Dog)animal;
        dog.name="遇见";
        dog.wangwang();

在这里插入图片描述
当然,向下转型是十分不安全的

Animal animal=new Dog();

        //向下转型
        /*Dog dog=(Dog)animal;
        dog.name="遇见";
        dog.wangwang()*/;
        Bird bird=(Bird)animal;
        bird.fly();

当我们用Bird对象引用Dog对象时,编译没问题,但运行时则会发生错误。

在这里插入图片描述
那么如何解决呢?这里我们可以使用instanceof这个关键字。

 if(animal instanceof Bird) {
            Bird bird = (Bird) animal;
            bird.fly();
        }

此时,animal如果不是引用了Bird这个对象,则不会进入if语句。

写到这,继承和多态就大致结束了,如有补充,欢迎各位大佬留言。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java是一种面向对象的编程语言,面向对象的三大特征是封装、继承多态继承多态是面向对象编程中非常重要的概念,下面将详细介绍它们。 继承是指创建一个新,从已有的中派生出来,新具有与父相同的属性和方法。在Java中,使用关键字`extends`来实现继承,即在新的声明中,加上`extends`关键字,后面跟上父的名称。示例如下: ``` public class Animal { public void eat() { System.out.println("动物吃东西"); } } public class Dog extends Animal { public void bark() { System.out.println("狗叫"); } } ``` 在上面的示例中,`Dog`继承了`Animal`,因此它可以使用`Animal`中的`eat()`方法,同时还有自己的`bark()`方法。 多态是指同一种型的对象,在不同的情况下会表现出不同的行为。在Java中,多态通过方法重载和方法覆盖来实现。方法重载是指在同一个中定义多个方法,它们具有相同的名称但参数列表不同。方法覆盖是指子重写父的方法,使得子的方法覆盖了父的方法。示例如下: ``` public class Animal { public void eat() { System.out.println("动物吃东西"); } } public class Dog extends Animal { public void eat() { System.out.println("狗吃肉"); } } public class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } } ``` 在上面的示例中,`Dog`和`Cat`都重写了`Animal`中的`eat()`方法,使得它们的行为不同。当我们创建`Animal`、`Dog`和`Cat`对象时,调用它们的`eat()`方法时会表现出不同的行为,这就是多态的体现。 继承多态是面向对象编程中非常重要的概念,它们可以让代码更加灵活和易于维护。在实际的编程中,我们需要灵活运用它们来设计出合理的结构和方法结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值