• Java面向对象(二)_封装、static、继承、多态、抽象、接口


    备注:如有错误请给予联系

    1. 面向对象的封装特性

    在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。

    封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

    要访问该类的代码和数据,必须通过严格的接口控制。

    封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。

    适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

     

    封装的优点

    1. 良好的封装能够减少耦合。

    2. 类内部的结构可以自由修改。

    3. 可以对成员变量进行更精确的控制。

    4. 隐藏信息,实现细节。

    实现Java封装的步骤

    1. 修改属性的可见性来限制对属性的访问(一般限制为private),例如:

    1 public class Person { 
    2 private String name; 
    3 private int age; 
    4 }

    这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。

    2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:

    1 public class Person{ 
    2 private String name; 
    3 private int age; ​ 
    4 public int getAge(){ return age; } ​ 
    5 public String getName(){ return name; } ​ 
    6 public void setAge(int age){ this.age = age; } ​ 
    7 public void setName(String name){ this.name = name; } 
    8 }

    采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。

    2.静态属性、静态方法、静态代码块

    Java语言中,static表示静态的意思,使用场景可以用来修饰成员变量和成员方法,当然也可以是静态代码块。

    static的主要作用在于创建独立于具体对象的域变量或者方法。

    static要解决什么问题?

     

    我们知道,当我们通过new关键字去创建对象的时候,那么数据的存储空间才会被分配,类中的成员方法才能被对象所使用。

    但是呢有两种特殊的情况:

    1、我们通过new关键字创建的对象共享同一个资源,而不是说每个对象都拥有自己的数据,

      或者说根本就不需要去创建对象,这个资源和对象之间是没有关系的。

    2、希望某个方法不与包含它的类的任何对象联系在一起。

    总结下来就是说:即使没有创建对象,也能使用属性和调用方法static目的就是在于解决这个问题。

     

    格式:

      修饰变量:static 数据类型 变量名

      修饰方法:【访问权限修饰符】 static 方法返回值 方法名(参数列表)

     

    特点:

    static可以修饰变量,方法被static修饰的变量或者方法是独立于该类的任何对象,也就是说,

    这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。

    在类被加载的时候,就会去加载被static修饰的部分。

    static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

     

    static静态变量:

    static修饰的成员变量叫做静态变量,也叫做类变量,说明这个变量是属于这个类的,

    而不是属于是对象,没有被static修饰的成员变量叫做实例变量,说明这个变量是属于某个具体的对象的。

    静态变量和实例变量的区别:

    实例变量:每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,

    在内存中,创建几次对象,就有几份成员变量

    静态变量:静态变量由于不属于任何实例对象,是属于类的,所以在内存中只会有一份,

    在类的加载过程中,JVM为静态变量分配一次内存空间。

     

    static静态方法

    static修饰的方法也叫做静态方法,因为对于静态方法来说是不属于任何实例对象的,

    那么就是说在静态方法内部是不能使用this的,因为既然不属于任何对象,那么就更谈不上this了。

    static应用场景

    如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。

    static如何去访问

    静态变量:

    类名.静态变量

    对象.静态变量(不推荐的)

    静态方法:

    类名.静态方法

    对象.静态方法(不推荐)

     

    静态代码块:

    java类中(方法中不能存在静态代码块)使用static关键字和{}声明的代码块:

    1 public class CodeBlock {
    2     static{
    3         System.out.println("静态代码块");
    4     }
    5 }

    静态代码块执行时机:静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数。

    如果一个类中有多个静态代码块,会按照书写顺序依次执行。后面在比较的时候会通过具体实例来证明。

    静态代码块的作用: 一般情况下,如果有些代码需要在项目启动的时候就执行,这时候就需要静态代码块。

    比如一个项目启动需要加载的很多配置文件等资源,我们就可以都放入静态代码块中。

    静态代码块不能访问普通变量

    拓展:构造代码块

    java类中使用{}声明的代码块(和静态代码块的区别是少了static关键字):

    1 public class CodeBlock {
    2     static{
    3         System.out.println("静态代码块");
    4     }
    5     {
    6         System.out.println("构造代码块");
    7     }
    8 }

    构造代码块执行时间:

    构造代码块在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造函数执行。

    需要注意的是,听名字我们就知道,构造代码块不是优先于构造函数执行,而是依托于构造函数,

    也就是说,如果你不实例化对象,构造代码块是不会执行的。怎么理解呢?我们看看下面这段代码:

     

     1 public class CodeBlock {
     2     {
     3         System.out.println("构造代码块");
     4     }
     5      public CodeBlock(){
     7         System.out.println("无参构造函数");
     8     }
     9     public CodeBlock(String str){
    10         System.out.println("有参构造函数");
    11     }
    12 }

     

    我们反编译生成的class文件:

     

     

    如果存在多个构造代码块,则执行顺序按照书写顺序依次执行。

    构造代码块的作用:和构造函数的作用类似,都能对对象进行初始化,并且只要创建一个对象,构造代码块都会执行一次。

    但是反过来,构造函数则不一定每个对象建立时都执行(多个构造函数情况下,建立对象时传入的参数不同则初始化使用对应的构造函数)。

      利用每次创建对象的时候都会提前调用一次构造代码块特性,我们可以做诸如统计创建对象的次数等功能。

    普通代码块: 普通代码块和构造代码块的区别是,构造代码块是在类中定义的,而普通代码块是在方法体中定义的。且普通代码块的执行顺序和书写顺序一致。

    1 public void sayHello(){
    2     {
    3         System.out.println("普通代码块");
    4     }
    5 }

    执行顺序:静态代码块>构造代码块>构造函数>普通代码块 

    父类和子类的执行顺序:对象的初始化顺序:

    首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,

    当子类的静态内容执行完毕之后,再去看父类有没有构造代码块,如果有就执行父类的构造代码块,父类的构造代码块执行完毕,接着执行父类的构造方法;

    父类的构造方法执行完毕之后,它接着去看子类有没有构造代码块,如果有就执行子类的构造代码块。子类的构造代码块执行完毕再去执行子类的构造方法。

      总之一句话,静态代码块内容先执行,接着执行父类构造代码块和构造方法,然后执行子类构造代码块和构造方法。

     

    3.面向对象的继承特性

    继承 面向对象软件技术当中的一个概念,与多态、抽象共为面向对象的三个基本特征。

    继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。

    继承(英语:inheritance)是面向对象软件技术当中的一个概念。

    如果一个类别A“继承自另一个类别B,就把这个A称为“B的子类别,而把B称为“A的父类别也可以称“BA的超类

    继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。

    在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。

    另外,为子类别追加新的属性和方法也是常见的做法。

    一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。

    那么如何使用继承呢?用extends关键字来继承父类。

    如上面A类与B类,当写继承语句时, class Aextends B{ } 其中A类是子类,B类是父类。

           1、子类拥有父类的特征,而父类没有,父类更通用,子类更具体,(特征包括属性和方法,自身的特性,拥有父类没有的)
      2、使用extends继承父类,语句格式:class 子类名 extends 父类名{}
      3、父类中一般只定义一般属性和方法(这个一般可以理解为是子类共有的,这就是父类更通用,而子类拥有其他的,所以子类更具体)
      4、子类中通过super关键字来调用父构造方法
      5、在子类中可以继承父类得那些东西,哪些不可以继承
        父类中publicprotected修饰的属性,方法可以继承,private修饰的属性和方法不能被继承
      6、规则: 创建子类对象的时候,首先调用的是父类的无参构造方法创建一个父类对象
      7、可以在子类中显示调用父类的有参构造方法
      8、如果父类的属性均为private修饰,则可以通过共有的gettersetter方法来调用

    有些编程语言支持多重继承,即一个子类别可以同时有多个父类别,比如C++编程语言;而在有些编程语言中,一个子类别只能继承自一个父类别,比如Java编程语言,这时可以利用接口来实现与多重继承相似的效果。

    现今面向对象程式设计技巧中,继承并非以继承类别的行为为主,而是继承类别的型态,使得元件的型态一致。另外在设计模式中提到一个守则,多用合成,少用继承,此守则也是用来处理继承无法在执行期动态扩充行为的遗憾。

    8.继承中构造方法的细节

    注意事项:

    1.父类无无参构造,子类可以用super(xxx)来解决。

    2.thissuper为平行关系,只能存在一个。

    3.子类无论如何都会访问父类中的一个构造方法,因为要看父类如何去初始化的。

    例子:

    A: 父类没有无参构造方法,子类怎么办?super解决this解决

    B:注意事项    super(…)或者this(….)必须出现在构造方法的第一条语句上

    4.面向对象的多态特性

    多态是同一个行为具有多个不同表现形式或形态的能力。

    多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:

    多态性是对象多种表现形式的体现。

    现实中,比如我们按下 F1 键这个动作:

    • 如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;
    • 如果当前在 Word 下弹出的就是 Word 帮助;
    • Windows 下弹出的就是 Windows 帮助和支持。

    同一个事件发生在不同的对象上会产生不同的结果。

     

    简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

    多态的优点

    • 1. 消除类型之间的耦合关系
    • 2. 可替换性
    • 3. 可扩充性
    • 4. 接口性
    • 5. 灵活性
    • 6. 简化性

    多态存在的三个必要条件

    • 继承
    • 重写
    • 父类引用指向子类对象

    比如:

    Parent p = new Child();

    当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

    多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

    以下是一个多态实例的演示,详细说明请看注释:

     

     1 public class Test { 
     2 public static void main(String[] args) { 
     3 show(new Cat()); // 以 Cat 对象调用 show 方法 
     4 show(new Dog()); // 以 Dog 对象调用 show 方法 
     5 Animal a = new Cat(); // 向上转型 
     6 a.eat(); // 调用的是 Cat 的 eat 
     7 Cat c = (Cat)a; // 向下转型 
     8 c.work(); // 调用的是 Cat 的 work 
     9 } 
    10 public static void show(Animal a) {
    11 a.eat(); // 类型判断 
    12 if (a instanceof Cat) { // 猫做的事情 
    13 Cat c = (Cat)a; c.work(); 
    14 } else if (a instanceof Dog) { // 狗做的事情 
    15 Dog c = (Dog)a; c.work(); 
    16 } 
    17 } 
    18 } 
    19 abstract class Animal { 
    20 abstract void eat(); 
    21 } 
    22 class Cat extends Animal { 
    23 public void eat() { 
    24 System.out.println("吃鱼"); 
    25 } 
    26 public void work() { 
    27 System.out.println("抓老鼠"); 
    28 } } 
    29 class Dog extends Animal { 
    30 public void eat() { 
    31 System.out.println("吃骨头"); 
    32 } 
    33 public void work() { 
    34 System.out.println("看家"); 
    35 } 
    36 }

     

    执行以上程序,输出结果为:

    吃鱼

    抓老鼠

    吃骨头

    看家

    吃鱼

    抓老鼠

     

    虚函数

    虚函数的存在是为了多态。

    Java 中其实没有虚函数的概念,它的普通函数就相当于 C++ 的虚函数,动态绑定是Java的默认行为。

    如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数。

     

    重写

    我们将介绍在 Java 中,当设计类时,被重写的方法的行为怎样影响多态性。

    我们已经讨论了方法的重写,也就是子类能够重写父类的方法。

    当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。

    要想调用父类中被重写的方法,则必须使用关键字 super

     

    多态的实现方式

    方式一:重写

    方式二:接口

    方式三:抽象类和抽象方法

     

    5.抽象方法与抽象类

    在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

    抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

    由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。

    父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。

    Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。

    抽象类

    Java语言中使用abstract class来定义抽象类。如下实例:

    Employee.java 文件代码:

     1 /* 文件名 : Employee.java */ 
     2 public abstract class Employee { 
     3 private String name; 
     4 private String address; 
     5 private int number; 
     6 public Employee(String name, String address, int number) { 
     7 System.out.println("Constructing an Employee"); 
     8 this.name = name; 
     9 this.address = address; 
    10 this.number = number; 
    11 } 
    12 public double computePay() {
    13  System.out.println("Inside Employee computePay"); 
    14 return 0.0; 
    15 } 
    16 public void mailCheck() { 
    17 System.out.println("Mailing a check to " + this.name + " " + this.address); 
    18 } 
    19 public String toString() { 
    20 return name + " " + address + " " + number; 
    21 } 
    22 public String getName() { return name; } 
    23 public String getAddress() { return address; } 
    24 public void setAddress(String newAddress) { 
    25 address = newAddress; 
    26 } 
    27 public int getNumber() { return number; } 
    28 }

    注意到该 Employee 类没有什么不同,尽管该类是抽象类,但是它仍然有 3 个成员变量,7 个成员方法和 1 个构造方法。

    现在如果你尝试如下的例子:

    1 /* 文件名 : AbstractDemo.java */ 
    2 public class AbstractDemo {
    3  public static void main(String [] args) { 
    4 /* 以下是不允许的,会引发错误 */ 
    5 Employee e = new Employee("George W.", "Houston, TX", 43); 
    System.out.println(" Call mailCheck using Employee reference--"); 6 e.mailCheck(); 7 } 8 }

    当你尝试编译AbstractDemo类时,会产生如下错误:

    Employee.java:46: Employee is abstract; cannot be instantiated

          Employee e = new Employee("George W.", "Houston, TX", 43);

                       ^1 error

    继承抽象类

    我们能通过一般的方法继承Employee类:

    Salary.java 文件代码:

     1 /* 文件名 : Salary.java */ 
     2 public class Salary extends Employee { 
     3 private double salary; //Annual salary 
     4 public Salary(String name, String address, int number,double salary) { 
     6 super(name, address, number); 
     7 setSalary(salary); 
     8 } 
     9 public void mailCheck() { 
    10 System.out.println("Within mailCheck of Salary class "); 
    System.out.println("Mailing check to " + getName() + " with salary " + salary); 11 } 12 public double getSalary() { return salary; } 13 public void setSalary(double newSalary) { 14 if(newSalary >= 0.0) { salary = newSalary; } 15 } 16 public double computePay() { 17 System.out.println("Computing salary pay for " + getName());
    return salary/52; 18 } 19 }

    尽管我们不能实例化一个 Employee 类的对象,但是如果我们实例化一个 Salary 类对象,

    该对象将从 Employee 类继承 7 个成员方法,且通过该方法可以设置或获取三个成员变量。

    AbstractDemo.java 文件代码:

    1 /* 文件名 : AbstractDemo.java */
    2 public class AbstractDemo { 
    3 public static void main(String [] args) { 
    4 Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
    5 Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00); 
    System.out.println("Call mailCheck using Salary reference --");
    s.mailCheck();
    6 System.out.println(" Call mailCheck using Employee reference--"); 7 e.mailCheck(); 8 } 9 }

    以上程序编译运行结果如下:

    Constructing an EmployeeConstructing an EmployeeCall mailCheck using  Salary reference --Within mailCheck of Salary classMailing check to Mohd Mohtashim with salary 3600.0

    Call mailCheck using Employee reference--Within mailCheck of Salary classMailing check to John Adams with salary 2400.

    抽象方法

    如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。

    Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。

    抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。

    1 public abstract class Employee { 
    2 private String name; 
    3 private String address; 
    4 private int number; 
    5 public abstract double computePay(); //其余代码 
    6 }

    声明抽象方法会造成以下两个结果:

    • 如果一个类包含抽象方法,那么该类必须是抽象类。
    • 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。

    继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。

    最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。

    如果Salary类继承了Employee类,那么它必须实现computePay()方法:

    Salary.java 文件代码:

    1 /* 文件名 : Salary.java */ 
    2 public class Salary extends Employee { 
    3 private double salary; // Annual salary 
    4 public double computePay() { 
    5 System.out.println("Computing salary pay for " + getName()); 
    return salary/52; 6 } 7 //其余代码 8 }

    抽象类总结规定

    1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。

        只有抽象类的非抽象子类可以创建对象。

    2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

    3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

    4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

    5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

     

    6.接口的介绍

    接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。

    一个类通过继承接口的方式,从而来继承接口的抽象方法。

    接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

    除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

    接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

    接口与类相似点:

    一个接口可以有多个方法。

    接口文件保存在 .java 结尾的文件中,文件名使用接口名。

    接口的字节码文件保存在 .class 结尾的文件中。

    接口相应的字节码文件必须在与包名称相匹配的目录结构中。

    接口与类的区别:

    接口不能用于实例化对象。

    接口没有构造方法。

    接口中所有的方法必须是抽象方法。

    接口不能包含成员变量,除了 static 和 final 变量。

    接口不是被类继承了,而是要被类实现。

    接口支持多继承。

    接口特性

    接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。

    接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。

    接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

    抽象类和接口的区别

    1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。

    2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。

    3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。

    4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

    JDK 1.8 以后,接口里可以有静态方法和方法体了。

    接口的声明

    接口的声明语法格式如下:

    [可见度] interface 接口名称 [extends 其他的接口名] { 

    // 声明变量

     // 抽象方法 

    }

    Interface关键字用来声明一个接口。下面是接口声明的一个简单例子。

    NameOfInterface.java 文件代码:

    1  /* 文件名 : NameOfInterface.java */ 
    2 import java.lang.*; //引入包 
    3 public interface NameOfInterface { 
    4 //任何类型 final, static 字段 
    5 //抽象方法 
    6  }

    接口有以下特性:

    接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。

    接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。

    接口中的方法都是公有的。

    实例

    Animal.java 文件代码:

    1 /* 文件名 : Animal.java */ 
    2 interface Animal { 
    3 public void eat(); 
    4 public void travel(); 
    5 }

    接口的实现

    当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

    类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。

    实现一个接口的语法,可以使用这个公式:

    Animal.java 文件代码:

    ...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...

    实例

    MammalInt.java 文件代码:

     1 /* 文件名 : MammalInt.java */ 
     2 public class MammalInt implements Animal{ 
     3 public void eat(){ 
     4 System.out.println("Mammal eats"); 
     5 } 
     6 public void travel(){ 
     7 System.out.println("Mammal travels"); 
     8 } 
     9 public int noOfLegs(){ return 0; } 
    10 public static void main(String args[]){ 
    11 MammalInt m = new MammalInt(); 
    12 m.eat(); 
    13 m.travel(); 
    14  } 
    15 }

    以上实例编译运行结果如下:

    Mammal eatsMammal travels

    重写接口中声明的方法时,需要注意以下规则

    • 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
    • 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
    • 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。

    在实现接口的时候,也要注意一些规则

    • 一个类可以同时实现多个接口。
    • 一个类只能继承一个类,但是能实现多个接口。
    • 一个接口能继承另一个接口,这和类之间的继承比较相似。

    接口的继承

    一个接口能继承另一个接口,和类之间的继承方式比较相似。

    接口的继承使用extends关键字,子接口继承父接口的方法。

    下面的Sports接口被Hockey和Football接口继承:

     1 // 文件名: Sports.java 
     2 public interface Sports 
     3 { 
     4 public void setHomeTeam(String name); 
     5 public void setVisitingTeam(String name); 
     6 } 
     7 // 文件名: Football.java 
     8 public interface Football extends Sports { 
     9 public void homeTeamScored(int points); 
    10 public void visitingTeamScored(int points); 
    11 public void endOfQuarter(int quarter); } 
    12 // 文件名: Hockey.java 
    13 public interface Hockey extends Sports { 
    14 public void homeGoalScored(); 
    15 public void visitingGoalScored(); 
    16 public void endOfPeriod(int period); 
    17 public void overtimePeriod(int ot); 
    18 }

    Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。

    相似的,实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。

    接口的多继承

    Java中,类的多继承是不合法,但接口允许多继承。

    在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示:

    public interface Hockey extends Sports, Event

    以上的程序片段是合法定义的子接口,与类不同的是,接口允许多继承,而 Sports及 Event 可能定义或是继承相同的方法

    标记接口

    最常用的继承接口是没有包含任何方法的接口。

    标记接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。

    标记接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。

    例如:java.awt.event 包中的 MouseListener 接口继承的 java.util.EventListener 接口定义如下:

    1 package java.util; 
    2 public interface EventListener {}

    没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:

    • 建立一个公共的父接口:

    正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。

    • 向一个类添加数据类型:

    这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。

    参考网址:

    静态:

    https://baijiahao.baidu.com/s?id=1601254463089390982&wfr=spider&for=pc

    https://www.cnblogs.com/ysocean/p/8194428.html#_label0_0

    封装:https://www.runoob.com/java/java-encapsulation.html

    继承:https://baike.baidu.com/item/%E7%BB%A7%E6%89%BF/20267560?fr=aladdin

    多态:https://www.runoob.com/java/java-polymorphism.html

    抽象:https://www.runoob.com/java/java-abstraction.html

    接口:https://www.runoob.com/java/java-interfaces.html

  • 相关阅读:
    python 连接 mysql
    apt-get报错could not get lock /var/lib/dpkg/lock -open等
    二叉树两个结点的最低共同父节点
    c++虚函数,纯虚函数,抽象类,覆盖,重载,隐藏
    class的继承,从基类开始
    Vue.js简单记录
    转:MVC,MVP 和 MVVM 的图示
    转:springmvc常用注解标签详解
    《一头扎进SpringMvc视频教程》
    《一头扎进SpringMvc视频教程》Rest风格的资源URL
  • 原文地址:https://www.cnblogs.com/pmbb/p/11398677.html
Copyright © 2020-2023  润新知