当前位置:首页 » 《关注互联网》 » 正文

零基础Java第十四期:继承与多态(二)

16 人参与  2024年12月01日 12:01  分类 : 《关注互联网》  评论

点击全文阅读


目录

一、继承

1.1. 继承的方式

1.2. final关键字

 1.3. 继承与组合

1.4. protected关键字

二、多态 

2.1. 多态的概念 

 2.2. 向上转型

2.3. 重写 

2.4. 向下转型 

 2.5. 多态的优缺点


一、继承

1.1. 继承的方式

       猫类可以继承动物类,中华田园猫类可以继承猫类。同样地,在Java当中,可以实现以下几种继承方式:单继承、多层继承、不同类继承同一个类。但是,Java当中不支持多继承。

//单继承public class A{}public class B extends A{}//多层继承public class A{}public class B extends A{}public class C extends B{}//不同类继承同一个类public class A{}public class B extends A{}public class C extends A{} 

1.2. final关键字

(1)final关键字修饰变量或字段,表示常量,也就是不能修改。 

final int a = 10;a = 20;//这样会报错

(2)final关键字修饰数组 

final int[] array = new int[]{1,2,3};array = new int[]{10,20,30};//报错array[0] = 100;//不报错

         final修饰的是array这个引用变量本身,也就是array在栈上的地址不能被修改,就不能再去修改array里面的元素,但我们可以通过array的下标来进行访问。

(3) final修饰类

public final class Animal {    public int age;    public String name;}public class Dog extends Animal{    public void bark(){        System.out.println("汪汪叫");    }}

       此时Dog子类里面就会报错,继承关系将不会存在。查看Dog类里面String的源码,就可以看到String被final修饰了。

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence,               Constable, ConstantDesc {

 1.3. 继承与组合

      继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物 组合表示对象之间是apart-of的关系,比如:轮胎是汽车的一部分。

       面向对象中有一个比较重要的原则“多用组合、少用继”或者说“组合优于继承”。组合确实比继承更加灵活,也更有助于代码维护。 

1.4. protected关键字

二、多态 

2.1. 多态的概念 

       通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状态。总的来说:同一件事情,发生在不同对象身上,就会产生不同的结果。比如,猫在吃的行为是吃猫粮,而狗吃的是狗粮。但重要的是,我们要理解多态的思想。

 2.2. 向上转型

(1)直接赋值:父类引用子类对象 

public class Animal {    public int age;    public String name;    public Animal(int age, String name) {        this.age = age;        this.name = name;    }    public void eat(){        System.out.println("在吃饭");    }}public class Dog extends Animal{    public void bark(){        System.out.println("汪汪叫");    }    public void wag(){        System.out.println("摇尾巴");    }  public Dog(int age,String name){        super(age, name);    }}
public class Testdemo {    public static void main(String[] args) {        Animal animal = new Animal(10,"dahuang" );        Dog dog = new Dog("xiao",6);        animal = dog;//等价于      Aniaml animal = new Dog;        }}

(2)利用参数的传递

Dog dog = new Dog("大黄",5){     test1(dog);}public static void test1(Animal animal){}

 (3)返回值传参

public Animal test1(){     return new Dog("大黄",4);}

       以Animal作为一个接口,可以返回Dog,也可以返回Cat;参数也是一样可以接受Dog里面的形参,也可以接受Cat里面的形参。

      向上转型的缺点:不能调用到子类特有的方法。给大家举个简单的例子

    public Animal(int age, String name) {        this.age = age;        this.name = name;    }    public void eat(){        System.out.println("在吃饭");    }}public class Dog extends Animal{    public void bark(){        System.out.println("汪汪叫");    }}public class Testdemo {    public static void main(String[] args) {        Animal animal= new Dog(6,"小黑");        animal.eat();        animal.bark()://这样就会报错    }}

有了向上转型,就可以进行多态,但还得有另一个条件,就是实现重写。

2.3. 重写 

       多态实现条件:1. 必须在继承体系下 2. 子类必须要对父类中方法进行重写 3. 通过父类的引用调用重写的方法

        重写也可以成为覆盖。重写的好处在于子类可以根据需要,定义特定 于自己的行为。 也就是说子类能够根据需要实现父类的方法。

       方法重写的规则:1.方法名相同     2.参数列表相同(个数、数据类型、顺序都相同)     3.返回值相同    4.被重写的方法返回值类型可以不同,但是必须是具有父子关系的

       在Dog这个子类,我们不满足于只用父类里的方法,我们就可以通过编译器自动生成一个Override的方法,点击eat,就可以实现重写了。

 

//子类的@Overridepublic void eat() {    super.eat();}//父类的public void eat(){   System.out.println("在吃饭");}

       我们来看一下里面的源码,一直到Object类里面。Object就是所有子类的父类,包括Animal这个父类也是默认继承Object这个类里面。

 

       动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体 调用那个类的方法。 

      所以综上所述,动态绑定可以总结到以下两点:1.父类引用必须引用子类对象    2.子类重写父类的方法,通过父类引用调用被重写的方法

     注意:访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为protected父类被static、private修饰的方法、构造方法都不能被重写。

2.4. 向下转型 

 

上面我们讲到了向上转型,子类来调用父类的方法。那么,反过来就是向下转型。

public class Animal {    public int age;    public String name;    public Animal(int age, String name) {        this.age = age;        this.name = name;    }}public class Bird extends Animal{    public Bird(int age, String name) {        super(age, name);    }    public void fly(){        System.out.println("正在飞");    }}public class Testdemo {    public static void main(String[] args) {        Bird bird = animal;//产生报错    }}

       这里的错误原因就如同基本类型里面的long类型转成int类型,造成数据的丢失。同样在引用类型里面,大的也不能向小的转化。要想实行向下转型,就得强转。

Bird bird = (Bird)animal;

 再来看下面一段代码

Aniaml animal1 = new Dog(5,"旺财");Bird bird1 = (Bird)animal1animal1.fly();

 运行结果如下图所示:

       报错的原因为类型转化异常。Bird与Dog不是同一个类,因为强转而骗过了编译器,所以说,向下转型不安全。如果我们要避免这面这种错误,就可以使用下面的方法。

 if(animal instanceof Bird){            cat = (Cat)animal;            cat.mew();        }         if(animal instanceof Dog){            dog = (Dog)animal;            dog.bark();        }    }

 2.5. 多态的优缺点

    public static void eatfunc(Animal animal){        animal.eat();    }    public static void main(String[] args) {        Bird bird = new Bird(2,"金丝雀");        eatfunc(bird);        Dog dog = new Dog(5,"斯派克");        eatfunc(dog);        System.out.println(bird);        System.out.println(dog);    }

       以下是运行结果:可以看到Bird和Dog虽然都调用同一个父类里的eat方法,但经过对eat的方法重写之后,就会出现同一行为表现出不同的结果。

 

       优点:1. 能够降低代码的 "圈复杂度", 避免使用大量的 if - else       2.可扩展能力更强。如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低。

       缺陷:代码的运行效率降低。 1. 属性没有多态性 当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性   2. 构造方法没有多态性 


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/194876.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1