接口与抽象
本课程简要介绍了接口和抽象的概念,并提供了一些互动示例。
理解面向对象编程的概念非常重要。理解面向对象编程中的抽象思想是必不可少的。
在面向对象编程中使用接口非常巧妙,这一概念比表面看起来更需要关注。我们之前已经看到过一些抽象或封装的例子。类就是一个很好的抽象示例,它将所有细节隐藏起来,用户只需通过对象进行操作,而无需了解其背后的具体实现过程或设计蓝图。
接口将抽象的概念提升到了更高的层次。让我们通过一个具体的例子来理解它的运作方式。
编码示例:88
假设一所学校为了医疗目的需要测量每位学生的体重。学校管理部门聘请了一位承包商并签订了合同。学校并不关心具体如何完成这项工作,他们只关心最终的记录和合同的执行。学生们并不知道为什么他们的体重被测量。这个合同可以在其他领域中被复用。例如,一家图书公司可能希望比较他们出版书籍的页数,他们也可以实现同样的逻辑。
由于对象通常是名词,我们可以把接口看作是描述对象的形容词。在上述场景中,学生对象是可比较的,图书对象也是可比较的。
接口的另一个优势在于,我们可以实现多个接口,就像一个名词可以有多个形容词一样。一个人既是善良的又是诚实的。一个类既可以继承父类,又可以实现多个接口。下面的代码展示了相同的思想:
1/* 2类不能继承多个类 3因此不能这样写:public class CatyClass extends MobileClass, MobileFeatures 4 */ 5public class CatyClass extends MobileClass implements MobileUpgradable { 6 7 private double batteryStrength = 0.0; 8 private int pixel = 10; 9 private double mins = 60.0; 10 private int days = 0; 11 public double version = 1.0; 12 13 public double getVersion() { 14 return version; 15 } 16 17 public void setVersion(double version) { 18 this.version = version; 19 } 20 21 public double getBatteryStrength() { 22 return batteryStrength; 23 } 24 25 public void setBatteryStrength(double batteryStrength) { 26 this.batteryStrength = batteryStrength; 27 } 28 29 public double getMins() { 30 return mins; 31 } 32 33 public void setMins(double mins) { 34 this.mins = mins; 35 } 36 37 public double takeCharge(double mins){ 38 this.mins = mins; 39 return mins; 40 } 41 42 public double batteryCanLast(int days){ 43 this.days = days; 44 return days; 45 } 46 47 public CatyClass(){} 48 49 public CatyClass(String name, String color, double price, double mins){ 50 super(name, color, price); 51 this.mins = mins; 52 } 53 54}
在类声明之后,我们需要定义一个接口:
1interface MobileUpgradable { 2 double getVersion(); 3 void setVersion(double version); 4}
最后,我们需要编写主应用程序:
1public class ExampleEightyEight { 2 3 public static void main(String[] args) { 4 CatyClass catyOne = new CatyClass(); 5 catyOne.name = "New Caty"; 6 catyOne.setHeight(8.12); 7 System.out.println(catyOne.name + " has height of " + catyOne.getHeight() + " inches."); 8 System.out.println("The New Zeny mobile object has unique identifier: " + catyOne.hashCode()); 9 System.out.println(catyOne.name + " represents the " + catyOne.getClass()); 10 System.out.println(); 11 catyOne.version = 2.0; 12 System.out.println(catyOne.name + " has version " + catyOne.version); 13 catyOne.setVersion(3.0); 14 System.out.println(catyOne.name + " is upgraded to " + catyOne.getVersion()); 15 } 16}
代码说明
通过 MobileUpgradable 这个契约,新的移动设备对象实现了版本更新功能。这正是我们所做的事情。运行这段程序并观察控制台输出,你就能明白其中的原理。
默认情况下,接口中的方法是 public 和 abstract 的,因此在声明接口方法时无需显式写出这两个关键字。
编码示例:89
这个例子展示了我们之前讨论的内容。我们希望这个示例能让你对契约的实现有更清晰的理解。首先,我们将展示接口的代码片段,然后是两个实现了该契约的类,最后将它们整合到主应用程序中。
1public class Student implements Comparable { 2 public int weight; 3 4 public boolean isGreaterThan(Comparable toOther) { 5 Student otherStudent = (Student) toOther; 6 if (this.weight < otherStudent.weight) 7 return false; 8 else if (this.weight > otherStudent.weight) 9 return true; 10 else 11 return false; 12 } 13}
1public interface Comparable { 2 public boolean isGreaterThan(Comparable toOther); 3}
接下来是实现相同契约的 Book 类:
1public class Book implements Comparable { 2 public int pages; 3 4 public boolean isGreaterThan(Comparable toOther) { 5 Book otherBook = (Book) toOther; 6 if (this.pages < otherBook.pages) 7 return false; 8 else if (this.pages > otherBook.pages) 9 return true; 10 else 11 return false; 12 } 13}
最后是主应用程序部分:
1public class ExampleEightyNine { 2 public static void main(String[] args) { 3 Student st1 = new Student(); 4 Student st2 = new Student(); 5 st1.weight = 20; 6 st2.weight = 30; 7 System.out.println(st1.isGreaterThan(Comparable.class.cast(st2))); 8 System.out.println(); 9 Book b1 = new Book(); 10 Book b2 = new Book(); 11 b1.pages = 100; 12 b2.pages = 99; 13 System.out.println(b1.isGreaterThan(Comparable.class.cast(b2))); 14 } 15}