你如何使用你的接口的私有方法?

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。添加它们是为了更容易实现staticdefault 接口方法。 @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 中的公共方法中模拟私有方法

使用 FakeItEasy 的私有方法和属性的单元测试用例 [重复]

如何在 Linux 中找到你的 公网IP 地址

如何从docker将image镜像到私有的registry

如何使用 Apifox 来管理测试你的接口

如何将本地docker 镜像上传到我的私有仓库