简体   繁体   English

Java中私有成员变量的子类访问

[英]Subclass access of Private member variables in java

I've been really stumped on this question from "Data Structures and Algorithms" by Goodrich and Tamassia. Goodrich和Tamassia的“数据结构和算法”确实让我很困惑。 The book presents the following two classes: 该书分为以下两节课:

public class CreditCard {
private String customer;
private String bank;
private String account;
private int limit;
protected double balance;

public CreditCard(String customer, String bank, String account, int limit, double balance) {
    this.customer = customer;
    this.bank = bank;
    this.account = account;
    this.limit = limit;
    this.balance = balance;

}

public CreditCard(String customer, String bank, String account, int limit) {
    this(customer, bank, account, limit, 0.0);
}

public String getCustomer() { return this.customer; }
public String getBank() { return this.bank; }
public String getAccount() { return this.account; }
public int getLimit() { return this.limit; }
public double getBalance() { return this.balance; }

public boolean charge(double price) {
    if(price + this.balance > this.limit)
        return false;

    this.balance += price;
    return true;
}

public void makePayment(double amount) {
   if( amount < 0)
      System.out.println("Cannot process negative payment");
   else
      this.balance -= amount;
}

public void updateCreditLimit() {
    this.limit -= balance;
}

public static void printSummary(CreditCard card) {
    System.out.println("Customer = " + card.customer);
    System.out.println("Bank = " + card.bank);
    System.out.println("Account = " + card.account);
    System.out.println("Balance = " + card.balance);
    System.out.println("Limit = " + card.limit);
}

} }

Subclass 子类

public class PredatoryCreditCard extends CreditCard {
private double apr;

public PredatoryCreditCard(String customer, String bank, String account,
                           int limit, double balance, double apr) {
                               super(customer, bank, account, limit, balance);
                               this.apr = apr;
                           }

public void processMonth() {
    if(this.balance > 0) {
        double monthlyFactor = Math.pow(1 + apr, 1F/12);
        this.balance *= monthlyFactor;
    }
}

public boolean charge(double price) {
    boolean isSuccess = super.charge(price);
    if(!isSuccess)
        this.balance += 5;
    return isSuccess;
}

}

Question: 题:

Assume that we change the CreditCard class so that instance variable balance has private visibility. 假设我们更改了CreditCard类,以使实例变量balance具有私有可见性。 Why is the following two implementations of the PredatoryCreditCard.charge method flawed ? 为什么PredatoryCreditCard.charge方法的以下两个实现有缺陷?

public boolean charge(double price) {
    boolean isSuccess = super.charge(price);
    if(!isSuccess)
       charge(5); //penalty for late fee
     return isSuccess;
 }

Second one: 第二个:

public boolean charge(double price) {
    boolean isSuccess = super.charge(price);
    if(!isSuccess)
       super.charge(5); //penalty for late fee
     return isSuccess;
 }

What I understand is that a subclass can not directly manipulate a private field of it's super class. 我了解的是,子类不能直接操纵其超类的私有字段。 The field must be protected or public. 该字段必须是受保护的或公共的。 This allows us to say in the subclass this.balance += 5 . 这使我们可以在子类中说this.balance += 5 My understanding of the principles is not the issue, my problem is with the question i'm asked to answer. 我对原则的理解不是问题,我的问题是我要回答的问题。 From an implementation stand point, there is no flaw that I can clearly see in the PredatoryCreditCard.charge method as in both cases of the new implementation provided by the question, we are changing the balance field of the class regardless, because of the call to super. 从实现的角度来看,在PredatoryCreditCard.charge方法中没有明显的缺陷,因为在问题提供的新实现的两种情况下,我们都在更改类的balance字段,因为调用了超。 I can't find a flaw in the new implementation unless I think there is some hole in my knowledge of inheritance. 除非我认为我的继承知识存在一些漏洞,否则我无法在新实现中发现缺陷。

Thank you in advance. 先感谢您。

In either case, you can't be charged a fee if you are close enough to the balance that the fee (of value 5) would exceed your limit. 在这两种情况下,如果您的余额足够接近余额(费用值5)会超出您的限额,则不会向您收取费用。 And in the first case: 在第一种情况下:

public boolean charge(double price) {
    boolean isSuccess = super.charge(price);
    if(!isSuccess)
       charge(5); //penalty for late fee
     return isSuccess;
 }

What happens here when isSuccess fails? isSuccess失败时,这里会发生什么? We get stuck in infinite recursion calling this.charge(...) 我们陷入了调用this.charge(...)无限递归中

There are no syntax errors in either implementation. 两种实现方式都没有语法错误。 Both have (or may have) logic errors. 两者都有(或可能有)逻辑错误。

First Implementation 首次实施

public boolean charge(double price) {
    boolean isSuccess = super.charge(price);
    if(!isSuccess)
       charge(5);  //penalty for late fee
     return isSuccess;
 }

We start one level deep. 我们从一个层次开始。

The first statement is super.charge(price) . 第一个语句是super.charge(price)
If that statement returns false , then we call this.charge(5) . 如果该语句返回false ,则我们调用this.charge(5)
We are now two levels deep. 我们现在有两个层次。

The first statement is super.charge(5) . 第一个语句是super.charge(5)
If that statement returns false , then we call this.charge(5) . 如果该语句返回false ,则我们调用this.charge(5)
We are now three levels deep. 我们现在深了三个层次。

The first statement is super.charge(5) . 第一个语句是super.charge(5)
If that statement returns false , then we call this.charge(5) . 如果该语句返回false ,则我们调用this.charge(5)
We are now four levels deep. 我们现在有四个层次。
... ...

You get the point. 你明白了。 The first implementation can cause infinite recursion, which will then cause a stack overflow. 第一个实现可能导致无限递归,然后将导致堆栈溢出。 See What methods are there to avoid a stack overflow in a recursive algorithm? 请参阅有哪些方法可以避免递归算法中的堆栈溢出?

Second Implementation 第二次实施

public boolean charge(double price) {
    boolean isSuccess = super.charge(price);
    if(!isSuccess)
       super.charge(5); //penalty for late fee
     return isSuccess;
 }

We try to charge price . 我们试图收取price We record whether the transaction succeeded. 我们记录交易是否成功。
If the transaction fails, we try to charge a late fee. 如果交易失败,我们将收取滞纳金。 We do not record whether the transaction succeeded. 我们不记录交易是否成功。
If the late fee fails, we do not care. 如果滞纳金失败,我们不在乎。

I am not sure what the error is here. 我不确定这里是什么错误。 It certainly does not mimic how my bank works, but that is not necessarily a problem. 它当然不能模仿我的银行的运作方式,但这并不一定是问题。 I assume that avoiding late fees is a bad thing, but that really depends on your requirements. 我认为避免滞纳金是一件坏事,但这确实取决于您的要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM