面向对象程序之继承

本文详细介绍了面向对象编程中的继承概念,包括其原因、如何使用继承、继承中的成员访问规则、this与super的区别以及子类构造方法的执行顺序。同时提及了final关键字在变量、方法和类上的应用,以及继承与组合的区别。

 

目录

1.继承

1.1为什么要继承

1.2继承的概念

1.3如何使用继承

1.4父类成员访问

1.4.1子类中访问父类的成员变量

1.子类和父类不存在同名的成员变量

2.子类和父类存在同名成员变量

1.4.2子类对成员方法的访问

2.this和super的区别

3.子类的构造方法

2.代码块的执行顺序

 3.final关键字

3.1修饰变量或者字段,表示常量,不能修改

3.2修饰类,表示不能被继承

3.3修饰方法,表示不能重写

4.继承和组合


面向对象编程有三大特性:封装、继承、多态

在类和对象中已经介绍了封装,接下来讲继承

1.继承

1.1为什么要继承

java中使用类对现实世界中的实体进行描述,类经过实例化之后的对象,则可以用来表示现实中的实体,但是事物之间可以会存在一些关联,那么在设计程序是就得进行考虑。

比如,猫和狗

用java语言描述就是:

class dog{
    public String name;//名字
    public int age;//年龄
    public String color;//毛色 
    
    public void eat(){
        System.out.println("吃东西");
    }
        }
        
class Cat{
    public String name;//名字
    public int age;//年龄
    public String color;//毛色 
    
    public void bark(){
        System.out.println("正在叫");
    }
}

我们可以看到他们之中有着重复的内容,那么我们可以将这些共有的内容进行抽取,来实现代码的复用,这就叫继承。

1.2继承的概念

继承机制:是面向对象程序设计是代码可以复用 最重要的手段,它允许程序员在保持原有类的特性上进行扩展,增加新的功能,这样产生的类叫做派生类。

继承主要解决的问题:共性抽取,实现代码复用。

接上的狗和猫,我们可以利用继承的思想,把他们所共有的进行抽取

如下图:狗和猫继承动物的属性。

1.3如何使用继承

我们需要用到extends关键字。

例如:

修饰符 class 子类 extends 父类{

//...

对于狗和猫的例子,我们可更改为

class Animal{
    public String name;//名字
    public int age;//年龄
    public String color;//毛色
    public void sleep(){
        System.out.println("正在睡觉");
    }
}

class Animal{
    public String name;//名字
    public int age;//年龄
    public String color;//毛色
    public void sleep(){
        System.out.println("正在睡觉");
    }
}

class Dog extends Animal{

    public void eat(){
        System.out.println("吃东西");
    }
        }

class Cat extends Animal{
   public void bark(){
        System.out.println("正在叫");
    }
}
public class test {
    public static void main(String[] args) {
        Dog dog=new Dog();
        // dog类中并没有定义任何成员变量,name和age属性肯定是从父类Animal中继承下来的
        System.out.println(dog.name);
        System.out.println(dog.age);
        // dog访问的eat()和sleep()方法也是从Animal中继承下来的
        dog.sleep();
        dog.eat();
        Cat cat=new Cat();
        cat.bark();
    }
}

注意:

1.子类会讲过父类中的成员变量或者成员方法继承到子类中。

2.子类继承父类后,必须要有自己特有的成员,体现出于子类的不同,否则就没有必要继承了。

1.4父类成员访问

1.4.1子类中访问父类的成员变量

1.子类和父类不存在同名的成员变量
class base{
    public int a;
}
class derived extends base{
    public int b;
    public int c;
    public void method(){
        a=1;       //访问从父类中继承下来的a
        b = 20;    // 访问从父类中继承下来的b
        c = 30;    // 访问子类自己的c
    }
}

注意: 如果子类有的,优先访问子类,子类没有,就去访问父类看有没有,如果父类也没有,那就报错

2.子类和父类存在同名成员变量

我们再来看下,我们先给父类和子类中的成员变量初始化

class base{
    public int a=1;
    public int b=2;
}
class derived extends base {
    public int b=3;
    public int c=5;

    public void show() {
            System.out.println(a);
            System.out.println(b);
            System.out.println(c);
    }
}
public class test1 {
    public static void main(String[] args) {
        derived d = new derived();
        d.show();
    }

}

//结果:1 3 5

注意:

           如果访问的成员变量子类中有,优先访问自己的成员变量。

           如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。

            如果访问的成员变量与父类中成员变量同名,则优先访问自己的。

           成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。

那么,如果我们想访问父类中的成员变量,我们可以用super

class base{
    public int a=1;
    public int b=2;
}
class derived extends base {
    public int a=4;
    public int b=3;
    public int c=5;

    public void show() {
            System.out.println(super.a);//父类中的
            System.out.println(this.a);//子类中的
            System.out.println(super.b);//父类中的
            System.out.println(this.b);//子类中的
            System.out.println(c);      //子类中的
    }
}
public class test1 {
    public static void main(String[] args) {
        derived d = new derived();
        d.show();
    }

}

1.4.2子类对成员方法的访问


class Base{
    public void testA(){
        System.out.println("Base:testA()");
    }
    public void testB(){
        System.out.println("Base:testB()");
    }
}
class Derived extends Base{
    public void testA(){
        System.out.println("Derived: testA()");
    }
    public void testB(){
        System.out.println("Derived:testB()");
    }
    public void testC(){
        super.testA();//访问父类中的方法
        this.testA();//访问子类中的方法
        super.testB();//访问父类中的方法
        this.testB();//访问子类中的方法

    }
}
public class test3 {
    public static void main(String[] args) {
        Derived d=new Derived();
        d.testC();
    }
}

结果:

Base:testA()
Derived: testA()
Base:testB()
Derived:testB()

注意:

1.通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到 则访问,否则编译报错。

2.通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用 方法适传递的参数选择合适的方法访问,如果没有则报错

2.this和super的区别

this是对当前对象的引用,super是对当前对象父类的引用

this可以引用当前对象的成员,方法,构造方法

super可以引用当前对象中父类的成员,方法,构造方法。

注意:

1. 只能在非静态方法中使用

2. 在子类方法中,访问父类的成员变量和方法

3.子类的构造方法

class Base1{
    public Base1(){
        System.out.println("Base");
    }
}
class Derived1 extends Base1{
    public Derived1(){
        //super();
        System.out.println("Derived");
    }
}

public class test4 {
    public static void main(String[] args) {
        Derived1 d = new Derived1();
    }
}

结果:

Base
Derived

我们可以看到,在实例化子类对象时,子类在构造时,会先调用父类的构造方法,在调用子类的构造方法。为什么会这样?其实在子类的构造方法中,还隐藏着一个语句,super();

既然子类继承了父类中的成员,那么就需要先对父类中的成员进进行初始化,就先调用父类的构造方法,再调用子类自己的构造方法,将子类自己新增加的成员初始化完整。

注意:

1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构 造方法

2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的 父类构造方法调用,否则编译失败。

3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。

4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出

2.代码块的执行顺序

在类和对象中,最后讲了代码的执行顺序,那我再来看基于继承下,代码的执行顺序

class Base1{
    public Base1(){
        System.out.println("父类的构造");
    }
    static{
        System.out.println("父类的静态代码块");
    }
    {
        System.out.println("父类的实例化代码块");
    }
}
class Derived1 extends Base1{
    static{
        System.out.println("子类的静态代码块");
    }
    public Derived1(){
        System.out.println("子类的构造方法");
    }
    {
        System.out.println("子类的实例化代码块");
    }
}

 结果:

父类的静态代码块
子类的静态代码块
父类的实例化代码块
父类的构造
子类的实例化代码块
子类的构造方法
===================
父类的实例化代码块
父类的构造
子类的实例化代码块
子类的构造方法

我们可以看到,确实是在类和对象中所想的一致。

 3.final关键字

final关键字可以用来修饰变量、成员方法以及类

3.1修饰变量或者字段,表示常量,不能修改

 final int a = 1;
 a = 20;  // 编译出错

3.2修饰类,表示不能被继承


 inal public class Animal {
 ...
 }
 public class Bird extends Animal {
 ...
 }
 // 编译出错
无法对Animal进行继承

3.3修饰方法,表示不能重写

4.继承和组合

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

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

组合表示对象之间是has-a的关系,比如:汽车

想进一步理解继承和组合,这里可以看看这个网址深入了解继承与组合

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猪同学hy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值