Java中的接口:无法使实现的方法受保护或私有

Java中的接口:无法使实现的方法受保护或私有,java,interface,access-specifier,Java,Interface,Access Specifier,我知道接口必须是公共的。然而,我不想这样 我希望实现的方法只能从它们自己的包中访问,因此我希望实现的方法受到保护 问题是我无法保护接口或实现的方法 什么是工作环境?是否存在与此问题相关的设计模式 根据Java指南,抽象类也不能完成这项工作。您可以使用封装而不是继承 也就是说,创建你的类(它不会继承任何东西),并在其中拥有你想要扩展的对象的实例 然后你可以只暴露你想要的 这种方法的明显缺点是,必须显式地传递所有要公开的方法。而且它不会是一个子类…read 公共访问说明符表示该接口可由任何包中的任何

我知道接口必须是公共的。然而,我不想这样

我希望实现的方法只能从它们自己的包中访问,因此我希望实现的方法受到保护

问题是我无法保护接口或实现的方法

什么是工作环境?是否存在与此问题相关的设计模式


根据Java指南,抽象类也不能完成这项工作。

您可以使用封装而不是继承

也就是说,创建你的类(它不会继承任何东西),并在其中拥有你想要扩展的对象的实例

然后你可以只暴露你想要的

这种方法的明显缺点是,必须显式地传递所有要公开的方法。而且它不会是一个子类…

read

公共访问说明符表示该接口可由任何包中的任何类使用。如果不指定该接口为公共接口,则只有在与该接口相同的包中定义的类才能访问该接口。


这就是您想要的吗?

您的类可以使用包保护并仍然实现一个接口:

class Foo implements Runnable 
{
    public void run()
    {
    }
}
public interface Iface {
    public void doSomething();
}
package foo;
interface SomeProtectedFoo {
    int doSomeFoo();
}
如果您希望保护/打包某些方法,而不希望保护/打包其他方法,那么听起来您的类有不止一个职责,应该划分为多个

阅读此回复和其他回复的评论后进行编辑:

如果您认为方法的可见性会影响调用该方法的能力,请三思。如果不走极端,就无法阻止某人使用反射来标识类的方法并调用它们。然而,这不是问题:除非有人试图破解您的代码,否则他们不会调用随机方法

相反,将私有/受保护方法视为定义子类的契约,并使用接口定义与外部世界的契约


哦,对于那个决定我的例子应该使用K&R支撑的人:如果服务条款中有规定,当然可以。否则,你就找不到更好的方法来利用你的时间了吗?

下面是使用抽象类的方法

唯一不方便的是,它使您成为“子类”

根据java指南,您应该在大多数情况下遵循该建议,但我认为在这种情况下它是可以的

public abstract class Ab { 
    protected abstract void method();
    abstract void otherMethod();
    public static void main( String [] args ) { 
        Ab a = new AbImpl();
        a.method();
        a.otherMethod();
    }
}
class AbImpl extends Ab {
    protected void method(){
        System.out.println( "method invoked from: " + this.getClass().getName() );
    }
    void otherMethod(){ 
        System.out.println("This time \"default\" access from: " + this.getClass().getName()  );
    }
}

我只需要创建一个抽象类。这没有什么害处。

当我遇到这个问题时,我使用一个包可访问的内部或嵌套类来实现接口,将实现的方法从公共类中推出

通常这是因为我有一个带有特定公共API的类,它必须实现其他东西才能完成它的工作(通常是因为其他东西是伪装成接口的回调)——这在类似Comparable的情况下经常发生。我不希望公共API受到(强制公共)接口实现的污染

希望这有帮助

另外,如果您确实希望只由包访问方法,那么您不需要受保护的范围说明符,而是需要默认(省略)的范围说明符。当然,使用protected将允许子类查看方法


顺便说一句,我认为接口方法被推断为公共的原因是,只有一个接口是由同一个包中的类实现的,这在很大程度上是一个例外;它们通常被另一个包中的某些东西调用,这意味着它们需要公开。

这个问题基于一个错误的陈述:

我知道接口必须是公共的

不是真的,您可以使用默认访问修饰符创建接口

问题是我无法保护接口或实现的方法

这是:

C:\oreyes\cosas\java\interfaces>type a\*.java
a\Inter.java
package a;

interface Inter {
    public void face();
}

a\Face.java
package a;

class Face implements Inter {
    public void face() {
        System.out.println( "face" );
    }
}


C:\oreyes\cosas\java\interfaces>type b\*.java
b\Test.java

package b;
import a.Inter;
import a.Face;

public class Test {
    public static void main( String [] args ) {
        Inter inter = new Face();
        inter.face();
    }
}

C:\oreyes\cosas\java\interfaces>javac -d . a\*.java b\Test.java
b\Test.java:2: a.Inter is not public in a; cannot be accessed from outside package
import a.Inter;
        ^
b\Test.java:3: a.Face is not public in a; cannot be accessed from outside package
import a.Face;
        ^
b\Test.java:7: cannot find symbol
symbol  : class Inter
location: class b.Test
        Inter inter = new Face();
        ^
b\Test.java:7: cannot find symbol
symbol  : class Face
location: class b.Test
        Inter inter = new Face();
                          ^
4 errors

C:\oreyes\cosas\java\interfaces>

因此,要实现您想要的,就要防止在包之外使用接口和类。

对于一个接口,您要定义可由各种实现类公开的方法。 拥有一个带有受保护方法的接口就不能达到这个目的


我猜你的问题可以通过重新设计你的类层次来解决。

< P>这里有另一个解决方案,灵感来自C++ piml习惯用法。< /P> 如果希望实现接口,但不希望该实现是公共的,则可以创建实现该接口的匿名内部类的组合对象

这里有一个例子。假设您有这个接口:

class Foo implements Runnable 
{
    public void run()
    {
    }
}
public interface Iface {
    public void doSomething();
}
package foo;
interface SomeProtectedFoo {
    int doSomeFoo();
}
创建一个
Iface
类型的对象,并将实现放在其中:

public class IfaceUser {
    private int someValue;
    // Here's our implementor
    private Iface impl = new Iface() {
        public void doSomething() {
            someValue++;
        }
    };
}

无论何时需要调用
doSomething()
,您都可以在组合的
impl
对象上调用它。

我只是在尝试构建一个受保护的方法时遇到了这个问题,目的是只在测试用例中使用它。我想删除填充到DB表中的测试数据。不管怎么说,我的灵感来自于他的。不幸的是,它没有起作用。我确实找到了一种使用受保护的内部类使其工作的方法

界面:

class Foo implements Runnable 
{
    public void run()
    {
    }
}
public interface Iface {
    public void doSomething();
}
package foo;
interface SomeProtectedFoo {
    int doSomeFoo();
}
然后在公共类中定义为受保护的内部类:

package foo;
public class MyFoo implements SomePublicFoo {
    // public stuff
    protected class ProtectedFoo implements SomeProtectedFoo {
        public int doSomeFoo() { ... }
    }
    protected ProtectedFoo pFoo;
    protected ProtectedFoo gimmeFoo() {
        return new ProtectedFoo();
    }
}
然后,您只能从同一包中的其他类访问受保护的方法,因为我的测试代码如下所示:

package foo;
public class FooTest {
    MyFoo myFoo = new MyFoo();
    void doProtectedFoo() {
        myFoo.pFoo = myFoo.gimmeFoo();
        myFoo.pFoo.doSomeFoo();
    }
}

原来的海报有点晚了,但是嘿,我刚找到它D

解决这个问题的一种方法是(根据具体情况)创建一个匿名内部类,该类实现了受
保护的
私有的
作用域的接口。例如:

public class Foo {
    interface Callback {
        void hiddenMethod();
    }

    public Foo(Callback callback) {
    }
}
然后在
Foo
的用户中:

public class Bar {
    private Foo.Callback callback = new Foo.Callback() { 
        @Override public void hiddenMethod() { ... }
    };
    private Foo foo = new Foo(callback);
}
这样可以避免出现以下情况:

public class Bar implements Foo.Callback {
    private Foo foo = new Foo(this);

    // uh-oh! the method is public!
    @Override public void hiddenMethod() { ... }
}

我想你现在可以在Java9版本中使用它了。从Java 9的openJdk注释中

对接口中私有方法的支持也在考虑之中 作为添加对的支持的一部分,包含在JavaSE8中