• Java 基础之继承


    访问权限

    Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

    • default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
    • private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
    • public : 对所有类可见。使用对象:类、接口、变量、方法
    • protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

    请注意以下方法继承的规则:

    • 父类中声明为 public 的方法在子类中也必须为 public。
    • 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
    • 父类中声明为 private 的方法,不能够被继承。

    抽象类与接口

    1. 抽象类

    抽象类和抽象方法都使用 abstract 关键字进行声明。如果一个类中包含抽象方法,那么这个类必须声明为抽象类。
    抽象类和普通类最大的区别是,抽象类不能被实例化,只能被继承。

    public abstract class AbstractClassDemo {
    
        protected int x;
        private int y;
    
        public abstract void func1();
    
        public void func2() {
            System.out.println("func2");
        }
    }
    
    public class AbstractExtendClassDemo extends AbstractClassDemo {
        @Override
        public void func1() {
            System.out.println("func1");
        }
    }
    
    // AbstractClassDemo ac1 = new AbstractClassDemo(); // 'AbstractClassDemo' is abstract; cannot be instantiated
    AbstractClassDemo ac2 = new AbstractExtendClassDemo();
    ac2.func1();
    

    2. 接口

    接口是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。

    从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类,让它们都实现新增的方法。

    接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。

    接口的字段默认都是 static 和 final 的。

    public interface InterfaceExample {
    
        void func1();
    
        default void func2(){
            System.out.println("func2");
        }
    
        int x = 123;
        // int y;               // Variable 'y' might not have been initialized
        public int z = 0;       // Modifier 'public' is redundant for interface fields
        // private int k = 0;   // Modifier 'private' not allowed here
        // protected int l = 0; // Modifier 'protected' not allowed here
        // private void fun3(); // Modifier 'private' not allowed here
    }
    
    public class InterfaceImplementExample implements InterfaceExample {
        @Override
        public void func1() {
            System.out.println("func1");
        }
    }
    
    // InterfaceExample ie1 = new InterfaceExample(); // 'InterfaceExample' is abstract; cannot be instantiated
    InterfaceExample ie2 = new InterfaceImplementExample();
    ie2.func1();
    System.out.println(InterfaceExample.x);
    

    3. 比较

    • 从设计层面上看,抽象类提供了一种 IS-A 关系,需要满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求接口和实现接口的类具有 IS-A 关系。
    • 从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类。
    • 接口的字段只能是 static 和 final 类型的,而抽象类的字段没有这种限制。
    • 接口的成员只能是 public 的,而抽象类的成员可以有多种访问权限。

    4. 使用选择

    使用接口:

    • 需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Comparable 接口中的 compareTo() 方法;
    • 需要使用多重继承。

    使用抽象类:

    • 需要在几个相关的类中共享代码。
    • 需要能控制继承来的成员的访问权限,而不是都为 public。
    • 需要继承非静态和非常量字段。

    在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低。

    super

    • 访问父类的构造函数:可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始化的工作。应该注意到,子类一定会调用父类的构造函数来完成初始化工作,一般是调用父类的默认构造函数,如果子类需要调用父类其它构造函数,那么就可以使用 super() 函数。
    • 访问父类的成员:如果子类重写了父类的某个方法,可以通过使用 super 关键字来引用父类的方法实现。
    public class SuperExample {
    
        protected int x;
        protected int y;
    
        public SuperExample(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
        public void func() {
            System.out.println("SuperExample.func()");
        }
    }
    
    public class SuperExtendExample extends SuperExample {
    
        private int z;
    
        public SuperExtendExample(int x, int y, int z) {
            super(x, y);
            this.z = z;
        }
    
        @Override
        public void func() {
            super.func();
            System.out.println("SuperExtendExample.func()");
        }
    }
    
    SuperExample e = new SuperExtendExample(1, 2, 3);
    e.func();
    
    SuperExample.func()
    SuperExtendExample.func()
    

    重写与重载

    1. 重写(Override)

    存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。
    为了满足里式替换原则,重写有以下三个限制:

    • 子类方法的访问权限必须大于等于父类方法;
    • 子类方法的返回类型必须是父类方法返回类型或为其子类型。
    • 子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型。

    重写方法调用的优先级如下:

    • this.func(this)
    • super.func(this)
    • this.func(super)
    • super.func(super)

    2. 重载(Overload)

    在同一个类中,指一个方法与已存在的方法名称相同,但是参数类型、个数、顺序至少一个不同。
    注意:返回值不同,其他都相同不算数重载。

  • 相关阅读:
    SVN常用功能介绍(二)
    Excel文件导入SQL Server数据库
    ArcMap操作随记(2)
    ArcGIS温泉数据聚类分析、核密度分析
    ArcMap操作随记(1)
    ArcGIS下载安装
    新生报到问题(简单的数据采集)
    ArcGIS热点分析
    学校选址问题(学校用地适宜性分析)
    ArcScene数据与Sketchup数据的交互
  • 原文地址:https://www.cnblogs.com/breakfei/p/14085676.html
Copyright © 2020-2023  润新知