Interfaces in Java: cannot make implemented methods protected or private
我知道接口必须是公共的。不过,我不想这样。
我希望我的实现方法只能从它们自己的包中访问,所以我希望我的实现方法受到保护。
问题是我不能使接口或实现的方法受到保护。
什么是工作?是否有与此问题相关的设计模式?
从Java指南中,抽象类也不能胜任这项工作。
读这个。
"公共访问说明符指示接口可由任何包中的任何类使用。如果不指定该接口是公共的,则只有在该接口所在的包中定义的类才能访问该接口。"
这就是你想要的吗?
类可以使用包保护并仍然实现接口:
1 2 3 4 5 6 |
如果您希望某些方法受到保护/打包,而其他方法不受保护,那么您的类似乎有多个职责,应该拆分为多个。
阅读此回复和其他回复的评论后编辑:
如果您认为某个方法的可见性会影响调用该方法的能力,请重新考虑。如果不走极端,就不能阻止某人使用反射来标识类的方法并调用它们。但是,这不是问题:除非有人试图破解您的代码,否则他们不会调用随机方法。
相反,将私有/受保护的方法看作是为子类定义契约,并使用接口来定义与外部世界的契约。
哦,对于决定我的示例的人来说,应该使用K&R支撑:如果在服务条款中指定了它,当然。否则,你找不到更好的时间来做吗?
当我遇到这种情况时,我使用一个包可访问的内部类或嵌套类来实现接口,将实现的方法从公共类中推出。
通常是因为我有一个具有特定公共API的类,该类必须实现其他功能才能完成它的工作(通常是因为其他功能是伪装为接口的回调),这在类似于Comparable的情况下经常发生。我不希望公共API被(强制公共)接口实现污染。
希望这有帮助。
另外,如果您真的希望只由包访问方法,则不希望使用受保护的范围说明符,而是希望使用默认(省略)范围说明符。当然,使用protected将允许子类查看方法。
顺便说一句,我认为接口方法之所以被推断为公共的,是因为只有同一个包中的类才能实现接口,这在很大程度上是一个例外;它们常常被另一个包中的某些东西调用,这意味着它们需要是公共的。
这个问题是基于一个错误的陈述:
I know that an interface must be public
实际上,您可以使用默认访问修饰符来创建接口。
The problem is I can't make the interface or the implemented methods protected
这里是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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> |
因此,实现您想要的,防止在包外部使用接口和类。
下面介绍如何使用抽象类来完成。
唯一不方便的是它使您成为"子类"。
按照Java指南,你应该遵循"大多数"的建议,但我认为在这种情况下它会好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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() ); } } |
我只是在尝试构建一个受保护的方法时遇到这种情况,目的是只在测试用例中使用它。我想删除已经填充到DB表中的测试数据。不管怎么说,我是被@karl giesing的帖子所启发的。不幸的是,它不起作用。我确实找到了一种方法,可以使用一个受保护的内部类来实现它。
接口:
1 2 3 4 | package foo; interface SomeProtectedFoo { int doSomeFoo(); } |
然后在公共类中定义为受保护的内部类:
1 2 3 4 5 6 7 8 9 10 11 | 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(); } } |
然后,您只能从同一个包中的其他类访问受保护的方法,正如我的测试代码所示:
1 2 3 4 5 6 7 8 | package foo; public class FooTest { MyFoo myFoo = new MyFoo(); void doProtectedFoo() { myFoo.pFoo = myFoo.gimmeFoo(); myFoo.pFoo.doSomeFoo(); } } |
原来的海报有点晚了,但是嘿,我刚找到。D
这里有另一个解决方案,灵感来自C++ piml习惯用法。
如果希望实现接口,但不希望该实现是公共的,则可以创建一个由实现该接口的匿名内部类组成的对象。
这是一个例子。假设您有这个接口:
1 2 3 | public interface Iface { public void doSomething(); } |
创建
1 2 3 4 5 6 7 8 9 | public class IfaceUser { private int someValue; // Here's our implementor private Iface impl = new Iface() { public void doSomething() { someValue++; } }; } |
每当需要调用
我想你现在可以用Java 9发布了。从Java 9的OpenJDK注释中,
Support for private methods in interfaces was briefly in consideration
for inclusion in Java SE 8 as part of the effort to add support for
Lambda Expressions, but was withdrawn to enable better focus on higher
priority tasks for Java SE 8. It is now proposed that support for
private interface methods be undertaken thereby enabling non abstract
methods of an interface to share code between them.
请参阅https://bugs.openjdk.java.net/browse/jdk-8071453
解决这个问题的一种方法是(取决于具体情况)创建一个匿名的内部类,该类实现具有
1 2 3 4 5 6 7 8 | public class Foo { interface Callback { void hiddenMethod(); } public Foo(Callback callback) { } } |
然后在
1 2 3 4 5 6 | public class Bar { private Foo.Callback callback = new Foo.Callback() { @Override public void hiddenMethod() { ... } }; private Foo foo = new Foo(callback); } |
这样就避免了以下情况:
1 2 3 4 5 6 | public class Bar implements Foo.Callback { private Foo foo = new Foo(this); // uh-oh! the method is public! @Override public void hiddenMethod() { ... } } |
通过接口,您希望定义可以由各种实现类公开的方法。拥有一个带有受保护方法的接口并不能达到这个目的。
我猜你的问题可以通过重新设计你的类层次结构来解决。
我只创建一个抽象类。没有什么害处。
您可以使用封装而不是继承。
也就是说,创建您的类(它不会继承任何东西),并在其中包含要扩展的对象的实例。
然后你只能暴露你想要的。
这种方法的明显缺点是,必须为您想要公开的所有内容显式地传递方法。它不会是一个子类…