你如何使用你的接口的私有方法?
Posted
技术标签:
【中文标题】你如何使用你的接口的私有方法?【英文标题】:How do you use your interface's private methods? 【发布时间】:2019-04-12 14:51:46 【问题描述】:我在使用我在我的界面中实现的私有方法时遇到了问题。
我在我的RequestData
接口中私下实现了一个print(string, list)
方法,以隐藏实现,因为我不希望它被调用,除非由类的其他打印方法调用 - 但我将它包含在接口中,因为它正在运行与每个实现类相同。
问题是,当我尝试从实现RequestData
接口的FundingRequests
中使用print
方法时,它会显示错误-print
方法在RequestData
接口中的访问是私有的,所以找不到。
嗯...如果接口的私有方法无法从实现类中访问,您应该如何使用它们?
这是一个错误,还是我误解了接口?
界面:
package com.landbay.datamodel.data;
import java.util.List;
public interface RequestData<E>
void add(E newRequest);
List<E> getRequests();
List<E> getFulfilledRequests();
List<E> getUnfulfilledRequests();
void printRequests();
void printFulfilledRequests();
void printUnfulfilledRequests();
private void print(String listTitle, List<E> listToPrint)
StringBuilder string = new StringBuilder();
string.append(listTitle);
for (E request : listToPrint)
string.append("\n").append(request);
System.out.println(string);
违规类和方法:
public class FundingRequests implements RequestData<FundingRequest>
private TreeSet<FundingRequest> requests;
FundingRequests()
this.requests = new TreeSet<>();
...
@Override
public void printRequests()
print("",new ArrayList<>(requests));
【问题讨论】:
接口中的私有方法并不意味着被实现类使用,事实上不能使用private
。添加它们是为了更容易实现static
和default
接口方法。
@Slaw's on it,私有方法用于类内,受保护的(默认范围)成员对子类可见,如果您想对外部类可见,则需要公共范围.
@Slaw 好的,这很有趣 - 谢谢。
【参考方案1】:
私有方法是作为 Java 接口的一项功能提供的,以帮助在接口中编写默认方法,而无需重用代码。它们不打算用于实现继承。
如果你想继承和使用实现的方法,比如你在这里尝试的:
@Override
public void printRequests()
print("",new ArrayList<>(requests));
您想在超类中实现该方法并扩展该类,或者将该方法实现为接口中的默认方法。使用超类将是执行此操作的更传统方式。
使用您提供的代码,您可以执行以下操作:
class Printer
protected void print(String listTitle, List<E> listToPrint)
StringBuilder string = new StringBuilder();
string.append(listTitle);
for (E request : listToPrint)
string.append("\n").append(request);
然后扩展该类:
public class FundingRequests extends Printer implements RequestData<FundingRequest>
private TreeSet<FundingRequest> requests;
FundingRequests()
this.requests = new TreeSet<>();
...
@Override
public void printRequests()
print("",new ArrayList<>(requests));
虽然这会将您的课程限制为仅扩展该课程。更好的模式是将该方法实现为类中的公共静态方法,然后使用它,如下所示:
class Printer
public static void print(String listTitle, List<E> listToPrint)
StringBuilder string = new StringBuilder();
string.append(listTitle);
for (E request : listToPrint)
string.append("\n").append(request);
然后使用方法:
public class FundingRequests implements RequestData<FundingRequest>
private TreeSet<FundingRequest> requests;
FundingRequests()
this.requests = new TreeSet<>();
...
@Override
public void printRequests()
Printer.print("",new ArrayList<>(requests));
或者,如果你真的想发疯,你可以用抽象类来完成:
abstract class RequestData<E>
abstract void add(E newRequest);
abstract List<E> getRequests();
abstract List<E> getFulfilledRequests();
abstract List<E> getUnfulfilledRequests();
abstract void printRequests();
abstract void printFulfilledRequests();
abstract void printUnfulfilledRequests();
protected void print(String listTitle, List<E> listToPrint)
StringBuilder string = new StringBuilder();
string.append(listTitle);
for (E request : listToPrint)
string.append("\n").append(request);
System.out.println(string);
然后扩展该类:
public class FundingRequests extends RequestData<FundingRequest>
private TreeSet<FundingRequest> requests;
FundingRequests()
this.requests = new TreeSet<>();
// implement the abstract methods
@Override
public void printRequests()
print("",new ArrayList<>(requests));
【讨论】:
那么,我应该将接口更改为抽象类并从中扩展吗? 抽象类用于声明由扩展它的类以不同方式实现的方法。如果您想将方法实现分发给其他类,只需在具有公共或受保护范围的类中实现该方法,然后扩展该类。 我对抽象类的理解是,就像接口一样,它允许你指定必须实现的方法,但可以通过不同的方式来实现,但你也可以定义具体的方法(例如作为我的打印方法),那么抽象类不是完美的吗?当然——我可以只用那个单一的方法创建另一个方法,并在单独实现我的接口时从它扩展,但这不是额外的、不必要的步骤吗? 抽象类的问题在于它们将扩展类限制为仅扩展该类。尽管这是可能的,但这似乎不是您的意图,因为您正在编写一个界面。我用两个替代示例更新了我的答案。 非常感谢。我喜欢你的解决方案 - 我不知道为什么它对我来说并不明显。一个问题是,Printer 类显然无法识别“E”参数类型。鉴于要打印的列表包含不同的对象,如何解决这个问题?我需要重载方法吗?【参考方案2】:您可以简单地将 print()
方法完全取出,或者将其设为嵌套静态类。
public interface RequestData<E>
void add(E newRequest);
List<E> getRequests();
List<E> getFulfilledRequests();
List<E> getUnfulfilledRequests();
void printRequests();
void printFulfilledRequests();
void printUnfulfilledRequests();
public static final class Printer
protected static <E> void print(String listTitle, List<E> listToPrint)
StringBuilder string = new StringBuilder();
string.append(listTitle);
for (E request : listToPrint)
string.append("\n").append(request);
System.out.println(string);
public class FundingRequests implements RequestData<FundingRequest>
private TreeSet<FundingRequest> requests;
FundingRequests()
this.requests = new TreeSet<>();
...
@Override
public void printRequests()
Printer.print("",new ArrayList<>(requests));
这允许您将print()
保持在protected
的可访问性,但它会暴露Printer
嵌套的静态类,从public
的角度来看,它没有任何作用。如果可以创建 public
方法,您可以简单地将该方法定义为 public static
(即实用程序)方法。
【讨论】:
【参考方案3】:您应该使用受保护的修饰符。私有方法只能从同一个类访问,子类不能访问。
【讨论】:
你能在接口中拥有受保护的方法吗? OP 正在尝试使用不能具有protected
方法的接口来执行此操作。以上是关于你如何使用你的接口的私有方法?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JUnit 在 Spring Boot 中的公共方法中模拟私有方法