程序员

Java学习14:继承、方法覆盖

2020-10-09  本文已影响0人  苦难_69e0

继承extends

继承的作用:
基本作用:子类继承父类,代码可以得到复用。(这个不是重要的作用,是基本作用。)
主要(重要)作用:因为有了继承关系,才有了后期的方法覆盖和多态机制。
java中继承的语法格式:
class 类名 extends 父类名{
类体;
}
继承的相关特性:
1、B类继承A类,则成A类为超类(superclass)、父类、基类,B类则称为子类(subclass)、派生类、扩展类。

class A()
class B extends A()
我们平时聊天说的比较多的是:父类和子类。
superclass 父类
subclass 子类

2、java中的继承只支持单继承,不支持多继承,c++中支持多继承,这也是java体现简单性的一点,换句话说,java中不允许这样写代码:
class B extends A,C{},这是错误的。

3、虽然java中不支持多继承,但有的时候会产生间接继承的效果,
例如:class C extends B , class B extends A , 也就是说,C直接继承B,其实C还简介继承A。

4、java中规定,子类继承父类,除构造方法不能继承之外,剩下都可以继承。但是私有的属性无法在子类中直接访问。(父类中private修饰的不能在子类中直接访问,可以通过间接的手段去访问)

5、java中的类没有显示的继承任何类,则默认继承Object类,Object类是java语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有Object类型中所有的特征。

6、继承也存在一些缺点,例如:CreditAccount类继承Account类会导致他们之间的耦合度非常高,Account类发生改变之后会马上影响到CreditAccount类。
耦合度高,父类修改,子类受牵连。

子类继承父类之后,能使用子类对象调用父类方法么?
实际上这个问题有点蹊跷。
蹊跷在于:能使用子类对象调用父类方法
本质上,子类继承父类之后,是将父类继承过来的方法归为自己所有。实际上调用的也不是父类的方法,是他子类自己的方法(因为已经继承过来了,就属于自己的。)
那自然是可以了,子类继承父类之后,这个方法就属于子类了,当然可以使用子类对象来调用。

在实际开发中,满足什么条件的时候,我可以使用继承呢?
凡是采用“is a”能描述的,都可以继承。
例如:
Cat is a Animal:猫是一个动物
Dog is a Animal:狗是一个动物
CreditAccount is a Accout:信用卡账户是一个银行账户
......
假设以后的开发中,有一个A类,有一个B类,A类和B类确实也有重复的代码,那么他们两个之间就可以继承么?
不一定,还是要看一看他们之间是否能够使用is a 来描述。

java为什么比较好学?
是因为Java内置了一套旁发的类库,程序员不需要从0开始写代码,程序员可以基于这套庞大的类库进行“二次”开发。(开发速度较快,因为JDK内置的这套库实现了很多基础的功能。)
例如:String 是SUN编写的字符串类、System是SUN编写的系统类。
这些类都可以拿来直接使用。

分析System.ou.println("Hello World!");
System.out中,out后面没有小括号,说明out是变量名。
另外System是一个类名,直接使用类名System.out,说明out是一个静态变量。
System.out返回一个对象,然后采用“对象.”的方式访问println()方法。
System.ou.println("Hello World!");*中System、out、println都是标识符。
在editplus中的红色字体,表示这个类是SUN公司的JDK写好的一个类。

任何一个类,没有显示继承任何类,默认继承Object,那么Object类当中又哪些方法呢?老祖宗为我们提供了哪些方法?
toString()方法

public class Test{
  //Test默认继承Object
  //Test类当中是有toString()方法
  //不过toString()方法是一个实例方法,需要创建对象才能调用。

  /*
  public String toString(){
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
  }
  */

  public static void main(String[] args){
    //先new对象
    Test et = new Test();
    String reValue = er.toString();

    //2f92e0f4 可以“等同”看做对象在堆内存当中的内存地址。
    //实际上是内存地址i经过“哈希算法”  得出的16进制结果。
    System.out.println(reValue);//Test@2f92e0f4

    //如果直接输出“引用”呢?
     System.out.println(et);//Test@2f92e0f4
  }
}

Object类当中有很多方法,大部分看不懂,其中有一个叫做toString()的,经测试发现:
System.out.println(引用);
当直接输出一个“引用”的时候,println()方法会先自动调用“引用.toString()”,然后输出toString()方法的执行结果。

注意:当源码当中一个方法以“;”结尾,并且修饰符列表中有“native”关键字表示底层调用c++写的dll程序(dll动态链接库文件)

方法覆盖

子类继承父类中,有一些“行为”可能不需要改进,,有一些“行为”可能面临着必须改进。因为父类继承过来的方法已经无法满足子类的业务需求。
什么时候我们考虑使用“方法覆盖”?
子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,子类有权利对这个方法进行重新编写,有必要进行“方法的覆盖”。

方法覆盖又叫做方法重写,英语单词叫做:Override、Overwrite,都可以。
比较常见的:方法覆盖、方法重写、Override

在进行方法覆盖的时候,最好将父类中的方法原封不动的复制过来。(不建议手动编写)
方法覆盖,就是将继承过来的哪个方法给覆盖掉了,继承过来的方法没了。

重要结论:当子类对父类继承过来的方法进行“方法覆盖”之后,子类对象调用该方法的时候,一定执行覆盖之后的方法。

当我们代码怎么编写的时候,在代码级别上构成了方法覆盖呢
条件一:两个类必须要有继承关系。
条件二:重写之后的方法和之前的方法具有:相同的返回值类型、相同的方法名、相同的形式参数列表。
条件三:访问权限不能更低,可以更高。
条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少。

注意事项:
注意1:方法覆盖只是针对于方法,和属性无关。
注意2:私有方法无法覆盖。
注意3:构造方法不能被继承,所以构造方法也不能被覆盖。
注意4:方法覆盖只是针对于“实例方法”,“静态方法”覆盖没有意义。

方法重载和方法覆盖有什么区别?
方法重载发生在同一个类当中。
方法覆盖是发生在具有继承关系的父子类之间。
方法重载是一个类中,方法名相同,参数列表不同。
方法覆盖是具有继承关系的父子类,并且重写之后的方法必须和之前的方法一致:
方法名一致、参数列表一致、返回值类型一致。

方法覆盖的经典案例

一定要注意:方法覆盖/方法重写的时候,建议将父类的方法复制粘贴,这样比较保险。

public class Test00{
    public static void main(String[] args){
        //创建一个中国人对象
        ChinesePeople p1 = new ChinesePeople();
        p1.setName("张三");
        p1.speak();
        //创建一个美国人对象
        AmericanPeople p2 = new AmericanPeople();
        p2.setName("jack");
        p2.speak();
    }
}
class People{
    //属性
    private String name;
    //构造方法
    //无参数构造方法
    public People(){}
    //有参数构造方法
    public People(String name){
        this.name = name;
    }
    //setter and getter
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    //实例方法  人都会说话
    public void speak(){
        System.out.println(name + "......");
    }

}
//中国人类
class ChinesePeople extends People{
    //中国人说话时汉语
    //所以子类需要对父类的speak()方法进行重写
    public void speak(){
        System.out.println(this.getName() + "正在说汉语.");
    }
}
//美国人类
class AmericanPeople extends People{
    //美国人说话是英语
    //所以子类需要对父类的speak()方法进行重写
    public void speak(){
        System.out.println(this.getName() + " speak English.");
    }
}

Object类中的toString()方法

toString()方法的作用是:将“java对象”转换成“字符串的形式”。

Object类中toString()方法的默认实现是:
public String toString(){
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

toString:方法名的意思是转换成String
含义:调用一个java对象的toString()方法就可以将java对象转换成字符串的表示形式。

大多数的java类toString()方法都是需要覆盖的。因为Object类中提供的toString()方法输出的是一个java对象的内存地址。

toString()方法具体怎么进行覆盖?
格式可以自己定义,或者听需求(项目要求)的。

上一篇 下一篇

猜你喜欢

热点阅读