继承&多态&重写&重载 理解小结

java面向对象里边包含了:继承 多态 重载 重写
下面是查询到的有用资料和自己的理解的结合
一、继承
1、继承:继承顾名思义,就是子类继承了父类的特征(java里边的特征是方法)。可以使用 extends 和 implements 这两个关键字来实现继承。
区别:extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,JAVA中不支持多重继承,但是可以用接口来实现,extends只能继承一个类,implements可以实现多个接口.注:extend可以继承一个接口,但仍是一个接口,也需要implements之后才可用
e.g. class A extends B implements C,D,E
2、作用:先明确,大量重复的代码在编程中是十分不好的。如果我们想编写两个类,牛和马,那么他们共同的方法都有吃草
(1)extends 关键字例子

public class horse{
    private String name;
    public horse(String name){
        this.name = name;
    }
    public void eatGrass(){}
    public void sleep(){}
}

public class cow{
    private String name;
    public cow(String name){
        this.name = name;
    }
    public void eatGrass(){}
    public void sleep(){}

}

除了类型不一样,其他都一样,显得累赘。如果用了继承,让代码更简洁,变成总-分关系.两个方法直接继承了,修改以后:

public class grassAnimal{
    private String name;
    public grassAnimal(String name){
        this.name = name;
    }
    public void eatGrass(){}
    public void sleep(){}
}

public horse extends grassAnimal{
    public horse(String name){
    super(name);
    }
}
public cow extends grassAnimal{
    public horse(String name){
    super(name);
    }
}

注1:如何调用horse的sleep方法

grassAnimal a = new horse("horse");//向上转型
a.sleep();

但是如果horse有一个方法run,下面这样的写法是错的,因为编译的时候是使用grassAnimal的run方法来检查,如何能通过编译,运行的时候,才采用horse的run方法

grassAnimal a = new horse("horse");
a.run();

应该改成:

horse a = new horse("horse");
a.sleep();

下面这个例子更加清楚:

这里写图片描述

注2:一个例子

public class Wine {
    public void fun1(){
        System.out.println("Wine 的Fun.....");
        fun2();
    }

    public void fun2(){
        System.out.println("Wine 的Fun2...");
    }
}

public class JNC extends Wine{
    /**
     * @desc 子类重载父类方法
     *        父类中不存在该方法,向上转型后,父类是不能引用该方法的
     * @param a
     * @return void
     */
    public void fun1(String a){
        System.out.println("JNC 的 Fun1...");
        fun2();
    }

    /**
     * 子类重写父类方法
     * 指向子类的父类引用调用fun2时,必定是调用该方法
     */
    public void fun2(){
        System.out.println("JNC 的Fun2...");
    }
}

public class Test {
    public static void main(String[] args) {
        Wine a = new JNC();
        a.fun1();
    }
}

结果

Wine 的Fun.....
JNC 的Fun2...

只是因为实例化的JNC并没有fun1()无参数的方法,所以只能调用Wine的

(2)implement
如果使用interface来定义grassAnimal

public interface grassAnimal {
    public void eatGrass();
    public void sleep();
}

public class cow implements grassAnimal {
}
public class horse implements grassAnimal {
}

3、构造器
(1)解释:两种情况:父类的构造器没有参数,系统自动调用父类的无参构造器;父类的构造器有参数,需要通过super关键字才能调用父类的构造器(具体看例子分析)
(2)举例:

class SuperClass {
  private int n;
  SuperClass(){
    System.out.println("SuperClass()");
  }
  SuperClass(int n) {
    System.out.println("SuperClass(int n)");
    this.n = n;
  }
}
class SubClass extends SuperClass{
  private int n;
  SubClass(){
    super(300);
    System.out.println("SubClass");
  }  

  public SubClass(int n){
    System.out.println("SubClass(int n):"+n);
    this.n = n;
  }
}
public class TestSuperSub{
  public static void main (String args[]){
    SubClass sc = new SubClass();
    SubClass sc2 = new SubClass(200); 
  }
}

输出结果

SuperClass(int n)
SubClass
SuperClass()
SubClass(int n):200

为什么会有第三句的出现呢?
解释:
1、子类不能继承父类的构造器。
2、继承父类的时候,构造器不写super,这个时候,编译器会自动地添加一个空参数的缺省super构造器(父类无参数的构造器),此时如果父类中没有空参数的缺省构造器,那就会导致一个编译错误。(意思是,子类的每一个方法都有super,如果有参数,那就用父类有参数的构造器,如果不写的话,编译器依旧会给你加上super,采用父类无参数的构造器,如果不存在这个无参数构造器,编译出错)
例如:subClass的第二个方法

public SubClass(int n){
    System.out.println("SubClass(int n):"+n);
    this.n = n;
  }

补全后是,如果SuperClass没有空的构造器就编译出错了

public SubClass(int n){
    super();
    System.out.println("SubClass(int n):"+n);
    this.n = n;
  }

二、重载和重写
菜鸟教程
(图借鉴了菜鸟教程)
这里写图片描述

重载:Overloading (好多种,只是参数不同)
重写:Overriding(改变这个方法的实现方式)
这里写图片描述

三、多态
1、重写
2、接口
3、抽象方法

  • 抽象类不能被实例化,只能被其他类继承
  • 继承抽象类的子类必须把抽象类中的所有抽象成员都重写(实现)(除非子类也是抽象类)
  • 抽象类就是为了重写→多态(代码重用)

三种实现

引用看到的博客的一段话:“如何区分多态和继承”
继承:子类继承父类中所以的属性和方法,但是对于private的属相和方法,由于这个是父类的隐私,所以子类虽然是继承了,但是没有可以访问这些属性和方法的引用,所以相当于没有继承到。很多时候,可以理解为,没有继承。
多态:就是父类引用可以持有子类对象。这时候只能调用父类中的方法,而子类中特有方法是无法访问的,因为这个时候(编译时)你把他看作父类对象的原因,但是到了运行的时候,编译器就会发现这个父类引用中原来是一个子类的对像,所以如果父类和子类中有相同的方法时,调用的会是子类中的方法,而不是父类的。
可以这么说:编译时看父类,运行时看子类。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值