菜鸡的Java笔记 第十九

继承性的主要目的,继承的实现,继承的限制
        
        继承是面向对象中的第二大主要特点,其核心的本质在于:可以将父类的功能一直沿用下去
        
        为什么需要继承?
            那么为了更好的区分出之前学习的概念与现在程序的区别,下面通过两个具体的代码来进行研究
            例如:现在有俩个类:Person,Student,按照原始的方式,程序代码实现如下:
            

class Person{
    private String name;
    private int age;
    public void setName(String name){
        this.name = name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
}
class Student{
    private String name;
    private int age;
    private String school;
    public void setName(String name){
        this.name = name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public void setSchool(String school){
        this.school = school;
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
    public String getSchool(){
        return this.school;
    }
}
public class inherit{
    public static void main(String args[]){
        System.out.println();
    }
}                

                两个类出现有重复,而且最为关键的问题是学生从现实的角度来看一定是个人
                那么按照这样的理解就可以发现出现重复的核心问题所在了,就是两个类之间没有联系
                之前所编写的代码或者说之前所学习到的概念那么还不足以解决多个类之间的代码重复消除问题
Student 是比 Person 更加细化的定义范畴
                
        使用继承解决问题
            在java中可以利用继承的概念来实现父类代码的重用问题,程序中可以使用extennds 关键字实现继承操作的定义
            其使用的语法如下:
            class 子类 extends 父类{}
            需要注意点名词概念:
                子类:也被称为派生类
                extends虽然从本质上来讲属于继承概念,但是其翻译为扩展,扩充的意思
                父类 本质上在java中称为超类(Super Class)
            
            范例:继承的基本使用

class Person{
    private String name;
    private int age;
    public void setName(String name){
        this.name = name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
}
class Student extends Person{  // Student 是Person 的子类
    // 此时并没有在Student类里面定义任何的操作
}
public class inherit{
    public static void main(String args[]){
        Student stu = new Student();// 实例化子类对象
        stu.setName("少爷");//通过Person类继承而来
        stu.setAge(20);//通过Person类继承而来
        System.out.println("姓名:"+stu.getName+",年龄:"+stu.getAge());
    }
}
/*
结果
姓名:少爷,年龄:20
    */                

                通过以上的程序就可以发现一点:子类在继承了父类之中,那么对于父类的支持方法不会减少
                但是子类可以进一步扩充属于自己的属性与方法
                
                范例:继承的基本使用

class Person{
    private String name;
    private int age;
    public void setName(String name){
        this.name = name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
}
class Student extends Person{  // Student 是Person 的子类
    private String school; // 子类自己扩充的属性
    public void setSchool(String school){
        this.school = school;
    }
    public String getSchool(){
        return this.school;
    }
public class inherit{
    public static void main(String args[]){
        Student stu = new Student();// 实例化子类对象
        stu.setName("少爷");//通过Person类继承而来
        stu.setAge(20);//通过Person类继承而来
        stu.setSchool("清华");//子类自己扩充的属性
        System.out.println("姓名:"+stu.getName+",年龄:"+stu.getAge()+",学校:"+stu.getSchool());
    }
}
/*
结果
姓名:少爷,年龄:20,学校:五道口
*/            

                通过这样的继承实现发现:
                    父类的功能可以延续到子类继续使用,这样在某些父类不能够修改的情况下,就可以通过继承来实现功能的扩充
                    子类中至少可以维持父类的原始方法不变,也就是说在子类里面父类的方法功能不会减少
                
*/

/*    继承的使用限制
        虽然继承的核心目的在于扩充类中的已有功能,但是在实际的开发之中,继承的使用也是存在有诺干限制的,这些限制必须注意
        限制一:java不允许多重继承,也就是说一个子类只能够继承一个父类
                因为C++它支持多继承,也就是说一个子类可以同时继承多个父类
            范例:错误代码

class A{
        
}
class B{
        
}
class C extendsa A,B{
        
}
public class inherit{
    public static void main(String args[]){
        System.out.println();
    }
}                    

                那么为什么实际中会出现这种代码呢?
                其实本质上也只是希望C类可以同时继承A,B类的方法,但是由于这样的做法与现实生活有冲突,所以从java的角度就屏蔽了,但是有解决方案
                虽然java不允许多重继承,但是却允许多层继承,以下代码为方案:

class A{
        
}
class Bextendsa A{
        
}
class C extendsa B{
        
}
public class inherit{
    public static void main(String args[]){
        System.out.println();
    }
}                

                此时的C类实际上就具备有A,B类的全部定义,但是从实际的开发,这种继承的层次关系不要超过三层
                
        限制二:子类在继承父类之后会将父类中的全部结构继承下来,但是对于私有的操作属于隐式继承(子类不能直接调用),而所有的非私有操作属于显式继承(可以直接调用)
            范例:观察显式继承

class A{
    private String name:
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
}
class B extendsa A{
        
}
public class inherit{
    public static void main(String args[]){
        B b= new B();
        b.setName("少爷");
        System.out.println(b.getName());
    }
}

                现在对于子类B而言是存在name属性的,但是这个属性子类并不能够直接操作
                范例:子类B直接访问    

class A{
    private String name:
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
}
class B extendsa A{
    public void print(){
        System.out.println(name);
    }
}
public class inherit{
    public static void main(String args[]){
        B b= new B();
        b.setName("少爷");
        System.out.println(b.getName());
    }
}//结果程序出错                    

                    也就是说此时的name属于隐式继承,而所有的setter方法属于显式继承,显式继承可以直接调用,而隐式继承的只能够间接的操作或者不能够操作
                    
        限制三:在实例化子类对象时会默认调用子类的无参构造方法,但是在执行子类构造前会首先自动实例化父类构造为父类的对象实例化,也就是说父类对象永远早于子类对象的实例化
            范例:观察实例化过程

class A{
    public A(){
        System.out.println("***********************");
    }    
}
class B extends A{
    public B(){
        System.out.println("###########################");
    }
}
public class inherit{
    public static void main(String args[]){
        B b= new B();
    }
}
/*
结果:
***********************
###########################
*/                

                如果说现在非要为子类加上一个调用父类构造的标记,那么就可以使用“super()”的形式完成

class A{
    public A(){
        System.out.println("***********************");
    }    
}
class B extends A{
    public B(){
        super();  // 表示由子类构造调用父类构造
        System.out.println("###########################");
    }
}
public class inherit{
    public static void main(String args[]){
        B b= new B();
    }
}
/*
结果:
***********************
###########################
*/                

                也就是证明,在子类的构造之中其实一直隐藏了一行“super()”语句,但是在进行无参父类构造调用的时候,写上“super()”是没有意义的
                往往是在父类没有提供无参构造时使用的
                范例:错误代码

class A{
    public A(String name){
        System.out.println("***********************");
    }    
}
class B extends A{
    public B(){
        // super();  // 表示由子类构造调用父类构造
        System.out.println("###########################");
    }
}
public class inherit{
    public static void main(String args[]){
        B b= new B();
    }
}//结果程序出错                    

                这个时候很明显使用隐含的“super()”并不合适,所以应该明确的调用指定参数的构造方法

class A{
    public A(String name){
        System.out.println("***********************");
    }    
}
class B extends A{
    public B(String name){
        super(name);  // 表示由子类构造调用父类构造
        System.out.println("###########################");
    }
}
public class inherit{
    public static void main(String args[]){
        B b= new B("少爷");
    }
}                    

                在大多数情况下父类一般都会提供有无参构造方法,这个时候可以在子类构造中不出现“super()”的语句
                但是如果此时父类没有提供无参构造方法,那么子类就必须使用“super()”调用指定参数的构造方法

对于 super 调用构造方法的情况需要注意如下几项:
                    不管你子类怎么折腾都一定要去调用父类的构造方法,即:调用父类构造使用 super()
                    super() 是在子类中编写的,表示通过子类的构造方法去调用父类构造,必须放在子类构造方法的首行,不能与“this()”不能同时出现在构造方法之中,两者关系属于二选一
                    如果现在父类中没有提供无参构造方法,那么在子类构造之中必须明确的调用有参构造方法,必须使用 super 调用指定参数的父类构造
                    
                    this 是应用在本类的关键字,而 super 是应用在子类中的关键字,利用 super 找到父类结构

                分析:关于this()与super()的问题
                    在之前学习过this()表示调用本类的其他构造方法,而现在有了继承关系之后,可以使用super() 由子类调用父类中指定的构造方法,并且这两个语句都一定要出现在首行,也就是说这两个语句不能同时出现
                    
                范例:不让子类调用父类的构造

class A{
    public A(String name){
        System.out.println("***********************");
    }    
}
class B extends A{
    public B(){
        
    }
    public B(String name){                        
        this();//
        System.out.println("###########################");
    }
}
public class inherit{
    public static void main(String args[]){
        B b= new B("少爷");
    }
}                    

                在子类的构造方法中出现了“this()”,这样就不会出现“super()”的默认执行而转为调用本类的构造方法了
                那么这样是不是可以不调用父类构造了呢?
                
        总结
            1.继承的唯一好处就是进行了功能的扩充,并且java只支持单继承局限
            2.子类对象实例化时一定要先实例化父类对象,而后在实例化子类自己的对象

*/

原文地址:https://www.cnblogs.com/mysterious-killer/p/10065984.html