Java(十七)继承

21 阅读5分钟

继承是面向对象的三大特点之一。

那么,何为继承?

一个类的对象可以使用另一个类的对象中的成员,这种关系就称之为继承。

 

一:继承格式

继承关键字extends。

/**
 * 人类
 */
class person
{
 
}
/**
 * 学生类
 */
class student extends person
{
   
}

 

二:继承的优缺点

优点

1:提高了代码的复用性

2:让类与类之间产生了继承的关系,这是构成多态的前提条件。

3:减少代码冗余,增强类的功能扩展性。

缺点

提高了代码的耦合性。在开发中我们遵循:高内聚,低耦合的原则。

高内聚:指一个类的功能越强越好

低耦合:指一个类的关系越少越好

 

三:继承的特点

1:java只支持单继承,不可以多继承。

/**
 * 父亲类
 */
class fu
{
 
}
/**
 * 儿子类
 */
class zi extends fu
{
   
}

 

2:java类可以多层继承

/**
 * 爷爷类
 */
class ye
{
 
}
/**
 * 父亲类
 */
class fu extends ye
{
 
}
/**
 * 儿子类
 */
class zi extends fu
{
   
}

 

3:java类不支持循环继承

/**
 * 爷爷类
 */
class ye extends zi
{
 
}
/**
 * 父亲类
 */
class fu extends ye
{
 
}
/**
 * 儿子类
 */
class zi extends fu
{
   
}

这样写是不可以的。

 

四:继承后:成员变量、成员方法的访问特点

1:子类不能继承父类中被private关键字所修饰的成员变量和成员方法。

2:子类不能继承父类的构造方法。

3:在子类方法中访问成员(成员变量、成员方法)满足:就近原则,先子类局部范围找 然后子类成员范围找 然后父类成员范围找,如果父类范围还没有找到则报错。

如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办? 可以通过super关键字,指定访问父类的成员。

 

五:方法重写

Java子类重写父类方法标识: @Override

重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致。

私有方法不能被重写。

子类重写父类方法时,访问权限必须大于或者等于父类 (暂时了解 :缺省 < protected < public)

子类写一个与父类申明一样的方法覆盖父类的方法。 @Override注解可以校验重写是否正确,同时可读性好。

重写方法的名称和形参列表应该与被重写方法一致。 私有方法不能被重写。

重写父类的静态方法会报错的。

public class T06 {
    public static void main(String[] args) {
        person fu = new person();
        student stu = new student();
        fu.drink();
        stu.drink();
    }
}
/**
 * 人类
 */
class person
{
    public void drink()
    {
        System.out.println("父类喝水");
    }
}
/**
 * 学生类
 */
class student extends person
{
    @Override
    public void drink()
    {
        System.out.println("子类喝水");
    }
}

输出:

父类喝水

子类喝水

 

六:this、super关键字

关键字访问成员变量访问成员方法访问构造方法
thisthis.成员变量 访问本类成员变量this.成员方法(…) 访问本类成员方法this(…)  访问本类构造方法
supersuper.成员变量 访问父类成员变量super.成员方法(…) 访问父类成员方法super(…) 访问父类构造方法

我们先来看下方的代码:

package d0131;
 
public class T05 {
    public static void main(String[] args) {
        student stu = new student();
        stu.drink();
    }
}
 
/**
 * 人类
 */
class person
{
    public int i = 1;
    public void drink()
    {
        System.out.println("父类喝水");
    }
}
/**
 * 学生类
 */
class student extends person
{
    int i = 2;
    @Override
    public void drink()
    {
        int i = 3;
        System.out.println(i);
        System.out.println(i);
        System.out.println(i);
    }
}

控制台输出:

3

3

3

那现在有一个小要求,要求控制台输出3/2/1,我们该如何实现呢?

这其中就需要使用到this以及super关键字。

代码如下所示:

public class T05 {
    public static void main(String[] args) {
        student stu = new student();
        stu.drink();
    }
}
 
/**
 * 人类
 */
class person
{
    public int i = 1;
    public void drink()
    {
        System.out.println("父类喝水");
    }
}
/**
 * 学生类
 */
class student extends person
{
    int i = 2;
    @Override
    public void drink()
    {
        int i = 3;
        System.out.println(i);
        // 当前这个类的成员变量i
        System.out.println(this.i);
        // 父类的成员变量i
        System.out.println(super.i);
    }
}

输出:

3

2

1

七:构造函数

1:子类的构造函数中,默认都加载了一次父类的构造函数,也就是super()

public class T01 {
    public static void main(String[] args) {
        zi zi1 = new zi();
        zi zi2 = new zi("xh");
    }
}
 
class fu
{
    public fu()
    {
        System.out.println("我被调用了!");
    }
 
    private String files;
 
    public String getFiles() {
        return files;
    }
 
    public void setFiles(String files) {
        this.files = files;
    }
}
 
class zi extends fu
{
    /**
     * 无参构造方法
     */
    public zi()
    {
        // 默认就有一个super方法
        // super();
    }
 
    /**
     * 重载有参构造方法
     * @param name
     */
    public zi(String name)
    {
        // 默认就有一个super方法
        // super();
    }
}

上边的程序,控制台输出:

我被调用了!

我被调用了!

 

为什么会有这样的现象呢?

因为有继承,说明子类可以使用父类的成员变量,那也就意味着父类的成员变量一定要有一直才可以被使用,所以在创建类对象的时候,会调用子类的构造方法,而子类的构造方法中会先去调用父类的构造方法,目的就是给父类的额成员变量默认初始化

 

2:子类的所有构造方法中,第一行要么是super(参数),要么是this(参数),他们不可以共存。并且子类中所有的构造方法中至少有一个构造方法里边调用的是super(参数)

class zi extends fu
{
    /**
     * 无参构造方法
     */
    public zi()
    {
        // 默认就有一个super方法
        // super();
        this("xxx");
    }
 
    /**
     * 重载有参构造方法
     * @param name
     */
    public zi(String name)
    {
        // 默认就有一个super方法
        // super();
        this();
    }
}

这样写是不行的。编译报错。死循环了属于是。

 

以上大概就是 java 继承的基本使用。

 

有好的建议,请在下方输入你的评论。