理解继承 组合 多态

Posted 3 ERROR(s)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解继承 组合 多态相关的知识,希望对你有一定的参考价值。


前言

代码中创建的类朱总要是抽象现实中的一些事物,有的时候客观事物之间就存在一些关联关系,那么表示成类和对象的时候也会存在一定的关联,例如有一个动物类,有一个猫类和一个狗类,这三个类存在了一定的联系,猫和狗都属于动物,他们都可以继承动物当中的一些属性从而达到代码重用的效果。

一、继承

1.继承使用背景

 Animal类
public class Animal 
    public String name;
    public Animal(String  name)
        this.name=name;
    
    public void eat(String food)
        System.out.println(this.name+"正在吃"+food);
    



猫类
public class Cat 
    public String name;
    public Cat(String name)
        this.name=name;
    
    public void eat(String food)
        System.out.println(this.name+"正在吃"+food);
    



狗类
public class Dog 
    public String name;
    public Dog(String name)
        this.name=name;
    
    public void eat(String food)
        System.out.println(this.name+"正在吃"+food);
    
    public void run()
        System.out.println(this.name+"i m running");
    


测试类
public class Test 
    public static void main(String[] args) 
        Animal animal=new Animal("动物");
        animal.eat("beef");

        Cat cat=new Cat("小猫");
        cat.eat("猫粮");

        Dog dog=new Dog("小狗");
        dog.eat("狗粮");
        dog.run();
    

结果:

  • 我们发现上面三个类都具备一个相同的eat方法,而且行为完全一致。
  • 并且他们都具备一个name属性。
  • 从逻辑上来说cat和dog都是animal的一种(is a 关系)

所以我们就可以让cat和dog继承animal类来达到代码的重用。

2.继承语法规则

class 子类 extends 父类
  • java中一个子类只能继承一个父类。
  • 子类会继承父类所有public的字段和方法
  • 对于父类的private的字段和方法,子类无法访问(但是继承了)
  • 可以使用super得到父类实例的引用。
使用继承之后新的Cat类
public class Cat extends Animal 
    public Cat(String name)
        super(name);
    


使用继承之后新的Dog类
public class Dog extends Animal

    public Dog(String name)
        super(name);
    
    public void run()
        System.out.println(this.name+"i m running");
    

3.protected关键字

当我们把父类中的字段改为private修饰之后会出现已下结果

因为private修饰的变量只能在类内被访问。
但是如果我们把访问修饰符改为public又违背了我们的初衷。
这时候protectde关键字的作用便发挥了出来。

+ private:类内部访问,类外部不能访问。
+ default:类内部能访问,用一个保重的类可以访问,其他类不能访问。
+ protected:类内部能访问,子类和同一个包中的类可以访问,其他类不可以访问。
+ public:类内部和类的调用者都可以访问

4.final关键字

我们的继承可以实现多层继承,但是实际的开发中我们一般不希望出现三层以上的继承关系,如果继承层次太多,就要考虑代码重构了。

当我们不想让一个类被继承的时候就要用到final关键字了。

final public class Animal 
    public String name;
    public Animal(String  name)
        this.name=name;
    
    public void eat(String food)
        System.out.println(this.name+"正在吃"+food);
    


我们可以发现当使用final修饰Animal类之后,Cat继承Animal会报错
final的三种用法:

  • final修饰变量:表示该变量不可被修改。
  • final修饰方法:表示该方法不能被重写。
  • final修饰类:表示该类不能被继承。

二、组合

和继承类似。组合也是一种表达类之间关系的方式,也能达到代码重用的效果。
组合表示has a语义

   老师类
public class Teacher 
    int age ;
    String  name;
    

学生类
public class Student 
    int age;
    String  name;
    

他们都属于学校
public class School 
   public Student [] students;
   public Teacher [] teachars;

三、多态

1.什么是多态?

  • 父类引用子类对象
  • 父类和子类有同名的覆盖方法
  • 通过父类引用代用子类这个重写的方法的时候发生运行时绑定,也可以称之为多态。
public class shape               父类
    public void draw()
    


class Cycle extends  shape            子类继承父类
    @Override
    public  void draw()                重写方法
        System.out.println("画了一个大圆圈");
    


class Rect extends  shape
    @Override
    public  void draw()
        System.out.println("画了一个正方形");
    


class Six extends  shape
    @Override
    public  void draw()
        System.out.println("画了一个666");
    


2.向上转型

刚才我们有这样一行代码

  Cat cat=new Cat("猫粮");

我们可以将它改写为以下形式

public class Test 
    public static void main(String[] args) 
        Cat cat=new Cat("小猫");
        Animal cat2=cat;
        animal.eat("猫粮");
    

或者这种形式

Animal cat2=new Cat("小猫");

此处的 cat2 是父类 Animal 的引用,他指向了子类 Cat 的实例 cat,这种现象我们称为向上转型。

向上转型发生的时机

  • 直接赋值
  • 作为参数传递
  • 作为方法的返回值传递。

3.动态绑定

定义:父类引用引用子类对象,同时父类引用调用同名的覆盖方法。


父类
public class Animal 
    public String name;
    public Animal(String  name)
        this.name=name;
    

    public void eat(String food)
        System.out.println("这是父类的eat方法");
        System.out.println(this.name+"正在吃"+food);
    



子类
public class Cat extends Animal 
    public Cat(String name)
        super(name);
    
    public void eat(String food)
        System.out.println("这是子类的eat方法");
        System.out.println(this.name+"正在吃"+food);
    


测试类
public class Test 
    public static void main(String[] args) 
        Animal animal = new Animal("小猫");
        Animal animal2=new Cat("小猫");
        animal.eat("饭饭");
        animal2.eat("饭饭");
    

  • animal ,animal2都是 Animal 类型的引用,但是animal 指向的是Animal 类型的实例,
  • animal2 指向的是 Cat类型的实例。
  • animal 调用了父类的 eat 方法,animal2 调用了子类的eat方法。

在调用javap -c之后我们看到在编译的时候animal调用的确实是父类的 eat( )方法,但是在运行的时候他却调用了子类的 eat( )方法,所以我们称他为运行时多态或动态绑定

4.方法重写

例如刚才的子类eat方法,
子类实现父类的同名方法,并且参数列表完全一样的时候,这种情况称为方法重写。

方法重写的注意事项:

  • 普通方法可以被重写,但是static修饰的方法不能被重写。
  • 子类方法的访问权限不能低于父类的访问权限。
  • 重写方法用@Override注解来标注。

方法重载和方法重写的区别

以上是关于理解继承 组合 多态的主要内容,如果未能解决你的问题,请参考以下文章

理解继承 组合 多态

java编程 类的继承及多态

深入理解Java中的组合和继承

JS面向对象三大特征:封装、继承、多态

Java 继承多态与类的复用

第二十六天 组合 封装 多态