【Big Java学习笔记】Chapter 9:Inheritance and Interfaces 继承和接口2

上一部分内容在这里:Inheritance and Interfaces 继承和接口1

当保留字 super 后跟括号()时,它表示对超类构造函数的调用。以这种方式使用时,构造函数调用必须是子类构造函数的第一条语句。另一方面,如果 super 后跟一个句点和一个 method 名称,则它表示对超类方法的调用,这样的调用可以在任何子类方法的任何地方进行。

-

Chapter 9.4 Polymorphism

learn how to use inheritance for processing objects of different types in the same program.

先解释一下 Polymorphism  是什么:Polymorphism 多态性(“具有多种形状”)允许我们操作共享一组任务的对象,即使这些任务以不同的方式执行。

虽然 method 需要传入超类对象,但我们可以用子类对象来替换,传入 method 中。在 Java 中,方法调用始终由实际对象的类型决定,而不是包含对象引用的变量的类型。 这称为动态方法查找。动态方法查找允许我们以统一的方式处理不同类的对象。此功能称为多态性。 我们要求多个对象执行一项任务,每个对象都以自己的方式执行任务。

(单看文字很抽象的,建议找个例子自己理解一下,这里我就不打代码了)

Abstract Classes

当扩展现有类时,可以选择是否覆盖 override 超类的方法。有时,需要强制程序员 override 一个方法。当超类没有好的默认 default 值时会发生这种情况,只有子类程序员才能知道如何正确实现该方法。

一个例子:假设 Java 第一国家银行决定每个账户类型都必须有一定的月费。 因此,应在 Account 类中添加一个 deductFees 方法:

public class Account
{ 
    public void deductFees() { . . . }
    . . .
}

但是这个 method 应该怎么做呢? 当然,可以让 method 什么都不做。 但是随后实现新子类的程序员可能会忘记实现 deductFees 方法。有一个更好的方法——将 deductFees 方法声明为抽象方法:

public abstract void deductFees();

抽象方法没有implementation。这会迫使子类的实现者指定此 method 的具体实现。一旦 Account 类具有抽象方法,编译器就会将创建新 Account() 的尝试标记为错误。An abstract method is a method whose implementation is not specified. An abstract class is a class that cannot be instantiated.

public abstract class Account
{ 
    public abstract void deductFees();
    . . .
}
public class SavingsAccount extends Account // Not abstract
{
    . . .
    public void deductFees() // Provides an implementation
    {
        . . .
    }
}

虽然不能构造抽象类的对象,但是可以拥有类型为抽象类的对象引用。 当然,它所引用的实际对象必须是具体子类的实例:

Account anAccount; // OK
anAccount = new Account(); // Error—Account is abstract
anAccount = new SavingsAccount(); // OK
anAccount = null; // OK

使用抽象类的原因是强迫程序员创建子类。通过将某些方法指定为抽象方法,可以避免其他人可能意外继承的无用默认方法的麻烦。

-

Chapter 9.5 Object: The Cosmic Superclass

The equals Method

和等号的区别:

if (stamp1.equals(stamp2)) . . .  // Contents are the same—see Figure 9
if (stamp1 == stamp2) . . .  // Objects are the same—see Figure 10

The instanceof Operator

在超类变量中存储子类引用是合法的,下面是个例子:

ChoiceQuestion cq = new ChoiceQuestion();
Question q = cq; // OK
Object obj = cq; // OK

偶尔,需要执行相反的转换,从超类引用到子类引用。 例如,有一个 Object 类型的变量,并且您碰巧知道它实际上hold一个 Question 引用。 在这种情况下,您可以使用强制转换来转换类型:

Question q = (Question) obj;

不过,这样转换有点危险。如果obj 实际上引用了一个不相关类型的对象,那么就会抛出一个“类转换”异常。为了防止错误的强制转换,可以使用 instanceof 运算符,它测试对象是否属于特定类型。 例如,obj instanceof Question。如果 obj 的类型可转换为 Question,则返回 true。 如果 obj 引用一个实际问题或一个子类,例如 ChoiceQuestion,就会发生这种情况。

-

Chapter 9.6 Interface Types

通过专注于算法所需的基本操作,通常可以设计出一个通用的、可重复使用的处理对象的机制。使用接口类型来表达这些操作。

例子:考虑以下方法,该方法计算一个 BankAccount 对象组成的数组中的平均余额。

public static double average(BankAccount[] objects)
{
    if (objects.length == 0) { return 0; }
    double sum = 0;
    for (BankAccount obj : objects)
    {
        sum = sum + obj.getBalance();
    }
    return sum / objects.length;
}

 现在假设有一个 Country 对象数组并想要确定这些区域的平均值:

public static double average(Country[] objects)
{
    if (objects.length == 0) { return 0; }
    double sum = 0;
    for (Country obj : objects)
    {
        sum = sum + obj.getArea();
    }
    return sum / objects.length;
}

显然,两种情况下计算结果的算法是相同的,但计算过程的细节不同。 如何编写一个通用方法来计算银行账户和国家的平均值?

假设这些类能够使用单一方法 getMeasure 来获取要在数据分析中使用的数据。对于银行账户,getMeasure 返回余额。 对于国家/地区,getMeasure 返回面积。然后我们可以实现一个单一的方法来计算:sum = sum + obj.getMeasure();

变量 obj 的类型是什么? 在 Java 中,接口类型用于指定所需的操作。我们将声明一个我们称之为 Measurable 的接口类型:

public interface Measurable
{
    double getMeasure();
}

Java 接口类型包含一组方法的返回类型、名称和参数变量。接口声明列出了接口类型需要的所有方法。 Measurable 接口类型需要一个方法,但一般来说,一个接口类型可以需要多个方法。 Unlike a class, an interface type provides no implementation.

接口类型类似于类,但有几个重要的区别:1)接口类型中的方法必须是抽象的。2)接口类型中的所有方法都是自动公开的。3)接口类型不能有实例变量。4)接口类型不能有静态方法。

我们可以使用接口类型 Measurable 来实现计算平均值的“通用”方法:

public static double average(Measurable[] objects)
{
    if (objects.length == 0) { return 0; }
    double sum = 0;
    for (Measurable obj : objects)
    {
        sum = sum + obj.getMeasure();
    }
    return sum / objects.length;
}

average 方法可用于实现 Measurable 接口的任何类的对象。如果类在 implements clause 中声明了接口,则该类实现了接口类型。 类应该实现接口所需的一个或多个抽象方法。 让我们修改 BankAccount 类来实现 Measurable 接口。

public class BankAccount implements Measurable
{ 
    public double getMeasure()
    {
        return balance;
    }
    . . .
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值