继承(java)

小白一枚,若有侵权,请指出,谢谢

面对对象程序设计三大特性之一:继承

继承

  在原有的类的基础之上,加以拓展,从而产生新的子类(is A关系),子类其实就是父类的一种特殊情况(开发时,抽取子类共性,形成父类)

 

继承的格式:class 子类名 extends 父类名(继承会破坏封装)

注意:object类是所有类的根类,一个类的直接父类或者间接父类都是object类。object 表示对象,object 类是对象的封装体


子类可以继承到父类的哪些成员?
     1.如果使用的public或者protected修饰,子类可以继承.
     2.如果使用是包访问权限(即属性或者方法修饰符不写的情况)如果子类和父类 在同包中,可以继承,否则不可以继承.
     3.父类的成员使用private,子类不能继承.
 
4.父类的构造器,子类不能继承.

构造器(构造方法):

子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器重写了带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。

如果父类有无参构造器,则在子类的构造器中不用super调用父类构造器,系统会优先自动调用父类的无参构造器。


注意:在java中,只允许单继承,但允许多重继承,但是一般不要超过五重继承。

 

 继承则会涉及到方法的覆盖(Override)

方法覆盖

使用原则:子类继承父类的时候,某个方法不适合子类本身,所以需要对父类的方法进行覆盖。


1.该方法若有返回值,子类的返回类型小于等于父类方法的返回类型    (例如:父类给long类型的返回值,则子类必须给小于等于long的类型)

2.子类方法不能抛出新的异常

3.子类方法的修饰符权限必须大于等于父类方法的修饰符

4.子类的方法要是想覆盖父类的方法,则方法的名称要相同,参数类型及个数要相同


最好的解决:
直接赋值父类的方法定义到子类,重新定义方法体
 
判断覆盖的准则
用@Override 判断是否覆盖

注意:方法的覆盖,重写,只能对方法有效。类,字段,构造器没有覆盖的概念
 

class Bird{
    protected void fly() {
        System.out.println("飞得更高");
    }
}

class Qier extends Bird {
    
    //覆盖了父类的fly()方法
    @Override
    protected void fly() {
        super.fly();
        System.out.println("折翼天使 飞不动 !!!!!!");
    }
}
public class OverrideDemo {
    public static void main(String[] args) {
        
        Bird b = new Bird();
        b.fly();
        
        System.out.println("------------------");
        
        Qier q = new Qier();
        q.fly();
        
        
    }
}

 super关键字

使用super关键字:指向当前对象的父类对象

 super的应用场景:
         1.在子类的方法中,调用父类被覆盖的方法 super.父类方法名()
         2.在子类方法中,返回父类被隐藏的成员变量
         3.在子类构造器中,调用父类的构造器

//动物类
class Animal1{
    private String name;
    private int age;
    
    public Animal1(String name,int age) {
        this.name = name;
        this.age = age;
    }
    public void say() {
        System.out.printf(this.name + "  年龄:" + this.age);
    }
}

//鱼类
class Fish extends Animal1{
    private String color;
    
    //构造器
    public Fish(String name,int age,String color) {
        super(name,age);//用super获取父类的字段
        this.color = color;
    }
    
    public void say() {
        super.say();//使用super获取父类被覆盖的方法
        System.out.printf("  颜色:" + color);
    }
}

//super关键字的使用
public class SuperDemo02 {
    public static void main(String[] args) {
        
        /*
         * 子类的创建过程
         * 先对父类初始化,再对子类初始化
         * 在调用子类构造器之前,会先调用父类构造器,若父类没有重写构造器,则调用系统默认的构造器(无参)。调用时严格区分无参构造器和有参构造器
         * 注意:若重写了构造器,则不能使用系统默认构造器
*/
        
        Fish f = new Fish("小丑鱼",1,"红色");
        f.say();
    }
}

this关键字

使用this关键字:指向当前对象哪个对象调用了this所在的成员,this就是哪个对象,哪一个对象调用this所在的方法,该方法中的方法的this就是哪一个对象


this的使用场景:
         1.解决成员变量和局部变量的二义性(必须使用setter方法)
         2.同一个类中多个实例方法间互调,当前类方法互调用this(默认可不写,标准化要写)
         3.将当前对象作为参数传递给另一个方法
         4.将当前对象作为方法的返回值

注意:
         1.构造器重载的互调,this必须写在第一行
         2.static不能与this一起使用

注意:
   1.静态方法不能覆盖,静态方法属于类方法,优先于对象的存在(若对静态方法覆盖会报错)

   2.静态方法与静态变量一样,属于类本身,而不属于类的某一个对象。

   3.调用一个被定义为静态(static)的方法,可以通过在它前面加上这个类的名称,也可以像调用非静态方法一样通过类对象调用。

public class ThisDemo {
    
    private String name = "成员变量";
    public int age;
    
    void setName(String name) {
        this.name = name;
    }
    
    //无参构造器
    public ThisDemo() {
        System.out.println("无参数构造器!");
    }
    
    //重写构造器,一个参数
    public ThisDemo(String name) {                       
        this();//调用无参构造器,必须写在第一行 若重写了构造器, 则不能使用系统默认构造器,这里会出错
        this.name = name;
    }
    
    //两个参数的构造器
    ThisDemo(String name,int age){
        this.name = name;
        this.age = age;
    }
    
    void show() {
        System.out.println("show");
    }
    
    void doWork() {
        String name = "局部变量";//局部变量和成员变量同名,局部变量隐藏成员变量,此时可使用this解决
        System.out.println(name);
System.out.println(this.name);
//将当前对象作为方法的返回值 ThisDemo append() { return this; } public static void main(String[] args) { //创建对象方法1 匿名对象,调用无参构造器 new ThisDemo();//若没有写构造器,系统默认会提供构造器。但是写了有参构造器(则系统不会再提供无参构造器),这里调用无参构造,会出错 //output:无参构造器! System.out.println("----------------"); //创建对象方法2 ThisDemo d = new ThisDemo("乔峰");//调用一个参数的构造器 output:无参构造器! 乔峰 System.out.println(d.name); System.out.println("----------------"); d.setName("lucy"); System.out.println(d.name);//output:lucky System.out.println("----------------"); new ThisDemo("zzz",45); System.out.println(d.name + "," + d.age);//output:lucky,0 为什么不是zzz,45?这里虽然调用了两个参数的构造器, //但是仍然用的是上面的引用对象,其值仍然为lucky,age为默认0 System.out.println("----------------"); //创建对象方法2 这里调用无参构造器 ThisDemo d2 = new ThisDemo();//output:无参构造器! System.out.println("----------------"); d2.show();//output:show System.out.println("----------------"); d2.doWork();//output:局部变量 ThisDemo d3 = d2.append();//这里通过append方法将当前对象作为方法的返回值,可以做其他操作 } }

1.局部变量和成员变量同名,局部变量隐藏成员变量,使用this关键字解决
 2.在满足继承条件下,子类存在和父类相同的成员变量,子类变量隐藏了父类变量,使用super解决
 3.在满足继承条件下,子类存在和父类相同的静态方法

坚持学习,永远年轻,永远热泪盈眶
原文地址:https://www.cnblogs.com/jiang0123/p/11279864.html