在抽象 class 方法中调用接口方法

invoking interface method in abstract class method

代码是 运行 但我想更好地理解主题,但我不确定如何命名问题。如果接口方法为空,我怎么可能在抽象 class 方法中调用接口方法?谁能告诉我这种操作在 Java 中是如何调用的?在我参加的大学 classes 中,幻灯片将问题命名为 "Programming through API" 但是当我 google 时我找不到任何东西。

我有一个接口 class,它有 getBalance 方法:

public interface BankAccount {

int getBalance();
...
}

然后我在抽象Class方法中调用接口方法:

public abstract class AbstractBankAccount implements BankAccount {

private final bankAccountNo;
private int accountBalance;  

abstractBankAccount(int bankAccountNo) {
    this.bankAccountNo = bankAccountNo;
}

public void transferBalance(bankAccount account) {

// so here is what I am struggling to understand: account.getBalance() is called, but getBalance() method in interface is empty, how does it work then? 

final int accountBal = account.getBalance();

    if (accountBal < 0)
        throw new IllegalArgumentException("not enough money on the account");

    accountBalance += accountBal;

    account.withdraw(accountBal);
}
}

抽象class一些方法留给具体的继承者去实现。

虽然该方法现在是空的(抽象的),但当您创建一个 non-abstract 实现时,您必须为该方法提供一个 body。 body 将被调用。

这是一个例子:

abstract class Parent {
  abstract String someMethod();

  public String getValue() {
    return someMethod();//how could this work?! someMethod() has no body!
  }
}

class Child extends Parent {

  @Override
  String someMethod() { //this won't compile unless I implement someMethod()
    return "data";
  }
}

虽然 someMethod() 在 Parent 中是抽象的,但实际上您不能创建 Parent 的实例(因为它是抽象的)。您必须扩展它,这需要您提供 someMethod() 的实现。

答案是,当这是 运行 时,account 参数将是实现 bankAccount.getBalance() 的具体 class 的实例。这就是抽象的工作原理

In my uni classes I attend, the slide names the problem as "Programming through API" but I cannot find anything when I google it.

How is it possible that in abstract class method I can invoke an interface method if the interface method is empty?

在具体的方法中class,你可能会遇到完全相同的情况。
这里的接口定义了一个契约:要实现的方法,但是这些在接口中都是抽象的。
要按接口编程,如果我们希望能够切换到另一个实现,那么操作放在接口(这里是 BankAccount)中的概念的代码不应该直接引用接口的具体 class 而应该是接口本身 [=接口的38=]。

这就是为什么 public void transferBalance(BankAccount account) 使用 BankAccount 类型作为参数定义的原因。

当然,必须一次选择并实例化一个具体的 class,但这是应该指定的唯一时间。

执行传输的客户端代码可以写成:

// I instantiate concrete classes but I refer interface as declared type.
BankAccount bankAcountDebitor = new ConcreteBankAccount();
BankAccount bankAcountCreditor = new ConcreteBankAccount();

// I invoke a method that takes as argument a type derived from the interface type 
bankAcountDebitor.transferBalance(bankAcountCreditor);

这样,就算有一天我们切换到另一个具体的BankAccount表示:

bankAcountDebitor.transferBalance(bankAcountCreditor);

仍然可以正常编译,因为该方法将接口类型作为参数。

所以你可以这样写:

BankAccount bankAcountDebitor = new ConcreteUniversalBankAccount();
BankAccount bankAcountCreditor = new ConcreteUniversalBankAccount();

bankAcountDebitor.transferBalance(bankAcountCreditor);