Java继承详解

一、为什么需要继承

现实世界错综复杂,但是事物之间也是有关联的

举个例子,先来看小猫小狗的类

class Dog{
    public String name;
    public int age;
    public String color;

    public void eat(){
        System.out.println(this.name+"吃饭");
    }
   
    public void bark(){
        System.out.println(this.name+"汪汪");
    }
}
class Cat{
    public String name;
    public int age;
    public String color;

    public void eat(){
        System.out.println(this.name+"吃饭");
    }

    public void miaomiao(){
        System.out.println(this.name+"喵喵");
    }
}

public class test {

    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "阿黄";
        dog.age = 1;
        dog.color = "白色";
        dog.eat();
        dog.bark();
        System.out.println("==============");
        Cat cat = new Cat();
        cat.name = "啊白";
        cat.age = 1;
        cat.color = "黑色";
        cat.eat();
        cat.miaomiao();
    }
}

小猫小狗都有共同的属性和行为,如名字、年龄、颜色、吃饭等,但是也有不同的行为,如叫声。

因此我们可以创建一个动物类,包含了两者的共同属性,之后猫狗类通过继承动物类得到它们共有的属性和行为。

class Animal{
    public String name;
    public int age;
    public String color;

    public Animal(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }
    public void eat(){
        System.out.println(this.name+"吃饭");
    }
}
//使用extends来继承
class Dog extends Animal{
    public void bark(){
        System.out.println(this.name+"汪汪");
    }
}

class Cat extends Animal{


    public Cat(String name, int age, String color) {
        super(name, age, color);
    }

    public void bark(){
        System.out.println(this.name+"喵喵");
    }
}

public class test {

    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.name);
        System.out.println(dog.age);
        dog.eat();
        dog.bark();
    }
   
}

二、继承的概念

简单来说就是共性的抽取,实现代码复用。

上述的小猫小狗类就是子类又称派生类

动物类就叫父类又称基类,超类。

可以当成is - a的关系

小猫(小狗)是一个小动物

三、继承的语法

修饰符  class  子类  extends  父类{

//。。。。

}

如:

class Dog extends Animal

class Cat extends Animal

四、父类成员的访问

1、子类怎么访问父类成员变量和方法:同名、不同名

(1)不同名

先在子类里找,找不到到父类里找,再找不到程序出错

(2)同名

优先访问子类,如果需要访问父类的成员变量需要用super关键字

访问成员:

class Base{
    public int a;
    public int b;
}
class Derived extends Base{
    public int c;
    public int a;

    public void test(){
        System.out.println(this.a);//子类,this包括子类和父类

        System.out.println(b);//子类没有就会访问父类

        System.out.println(c);//如果子类有优先访问子类
        //如果父类也没有就会报错
        //如果想访问父类的a,用super.成员

        System.out.println(super.a);//父类对象的引用
        //super只是一个关键字,提高了代码的可读性
        //不是引用,因为没有实例化对象,应理解成关键字
    }
}

public class test1 {
    public static void main(String[] args) {
        Derived derived = new Derived();
        derived.test();
    }
}

访问方法:

class Base2{
    public void testA(){
        System.out.println("testA()");
    }
}

class Derived2 extends Base2{
    public void testB(){
        System.out.println("testB()");
    }
    public void testA(){
        System.out.println("testA()");
    }
    public void testC(){
        this.testA();
        super.testA();
        this.testB();
    }
}
public class test2 {
    public static void main(String[] args) {
        Derived2 derived2 = new Derived2();
        derived2.testC();
        //静态方法里不能使用super和this
    }
}

五、继承的构造方法

子类要先帮助父类初始化成员变量,再给自己初始化

如果没有构造方法,系统会有默认的构造方法,如果自己提供了构造方法,就得调用自己的构造方法

class Animal{
    public String name;
    public int age;
    public String color;

    public Animal(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public void eat(){
        System.out.println(this.name+"吃饭");
    }
}

class Dog extends Animal{
   
    //调用构造方法
    public Dog(){
        super("大黄",10,"白色");//必须在第一行所以this和super不能同时在第一行
    }
    //快捷键
    //generate -》 constructor

    public Dog(String name, int age, String color) {
        super(name, age, color);
        //并没有产生父类对象
        //只是帮你初始化父类成员
    }
    //如果父类没有构造方法,就有默认的构造方法。如果父类有构造方法就不会提供,只能调用你写的
    public void bark(){
        System.out.println(this.name+"汪汪");
    }
}
class Cat extends Animal{
 
    public Cat(){
        super("小蓝",19,"蓝色");
    }

    public Cat(String name, int age, String color) {
        super(name, age, color);
    }

    public void miaomiao(){
        System.out.println(this.name+"喵喵");
    }
}

public class test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();
        dog.bark();
        System.out.println("==============");
        Cat cat = new Cat();
        cat.eat();
        cat.miaomiao();
    }
}

 super()用户不写也有,前提父类的构造方法是不带参数的,如果带参数了,就得用super( , , )

this()用户不写就没有

六、super和this

1、super和this的关系

2、super和this的区别

相同:

1、都只能在非静态方法中使用,用来访问非静态成员方法和字段

2、在构造方法中调用时,必须是构造方法中的第一条语句

不相同:

  1、super只是一个关键字,提高了代码的可读性,不是引用,因为没有实例化对象,所以应理解成关键字 ,即this有对象,super无对象。

2、this.data  this.func()  this()用于调用本类构造方法

3、super.data  super.func()  super()用于调用父类构造方法

4、this()和super()不能同时出现在构造方法的第一行

七、再谈初始化(继承)

class Animal{
    public String name;
    public int age;
    public String color;

    public Animal(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
        System.out.println("父类类构造方法");
    }

    {
        System.out.println("实例化代码块(父类)");
    }

    static{
        System.out.println("静态代码块(父类)");
    }

    public void eat(){
        System.out.println(this.name+"吃饭");
    }
}

class Cat extends Animal{

    {
        System.out.println("实例化代码块(子类)");
    }

    static{
        System.out.println("静态代码块(子类)");
    }
    public Cat(){
        super("小黄",10,"白色");
        System.out.println("子类构造方法");
    }

    public Cat(String name, int age, String color) {
        super(name, age, color);
        System.out.println("子类构造方法");
    }

    public void bark(){
        System.out.println(this.name+"喵喵");
    }
}

public class test {
    public static void main(String[] args){

        Cat cat = new Cat();
        System.out.println("==============");
        Cat cat2 = new Cat();

    }

}

运行结果

总结:

1、父类静态代码块优先于子类静态代码块执行,且是最早执行

2、父类实例代码块和父类构造方法紧接着执行

3、子类的实例代码块和子类构造方法紧接着再执行

4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

八、protected关键字

之前讲过包,protected不仅可以在同包的同类或不同类中使用,还可以在不同包中的子类使用,是一种温和的中间方式。

举例:

先来创建两个不同的包

第一个包是Demo2

package Demo2;

public class test3 {

    public int a = 0;

    protected int c = 99;

    public void func(){
        System.out.println(c);
    }

}

第二个包是Demo3,并且导入类test3,testDemo类继承test3的类,使用super.来接收父类的成员

package Demo3;
import Demo2.test3;


public class testDemo extends test3{

    public void func()
    {
        System.out.println(super.c);//static里不能用super

    }//protected成员变量可以在不同包中的子类使用,用super接收父类

    public static void main(String[] args) {

        testDemo test = new testDemo();
        test.func();
    }
}

注意:test3类必须是public修饰,如果不加就是包访问权限,不能在不同包使用,修饰类要么用public要么不加修饰。

那么什么时候用什么关键字来修饰呢?

类内部自己用:private

类调用者用:包访问权限(default)

子类用:protected

要思考过后再决定用什么。

九、继承方式

1、单继承

2、多层继承

3、不同类继承同一类

但是不允许同一类继承多个父类

为了避免这一情况,可以使用final关键字

final修饰继承类意味当前类不可以被继承,这个类叫密封类。

如果final修饰变量或字段,这个变量就成为了常量,不能被修改

如果final修饰方法表示该方法不能被重写(后序介绍)

十、继承与组合

组合是代码层次上的一种写法

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

组合并没有涉及到特殊的语法 (诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的成员。

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物

组合表示对象之间是has-a的关系,比如:汽车有轮胎、发动机、方向盘等

class Teacher{

}
class Student{

}
class School{
    public Teacher[] teachers;
    public Student[] students;
}

组合和继承都可以实现代码复用,应该使用继承还是组合,需要根据应用场景来选择,一般建议:能用组合尽量用组合。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值