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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/423032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:25:56  来源:igfitidea点击:

Interfaces in Java: cannot make implemented methods protected or private

javainterfaceaccess-specifier

提问by jbu

I know that an interface must be public. However, I don't want that.

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

I want my implemented methods to only be accessible from their own package, so I want my implemented methods to be protected.

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

The problem is I can't make the interface or the implemented methods protected.

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

What is a work around? Is there a design pattern that pertains to this problem?

什么是变通?是否有与此问题相关的设计模式?

From the Java guide, an abstract class wouldn't do the job either.

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

回答by Michael Haren

You can go with encapsulation instead of inheritance.

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

That is, create your class (which won't inherit anything) and in it, have an instance of the object you want to extend.

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

Then you can expose only what you want.

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

The obvious disadvantage of this is that you must explicitly pass-through methods for everything you want exposed. And it won't be a subclass...

这样做的明显缺点是您必须为想要公开的所有内容显式传递方法。它不会是一个子类......

回答by duffymo

read this.

这个

"The public access specifier indicates that the interface can be used by any class in any package. If you do not specify that the interface is public, your interface will be accessible only to classes defined in the same package as the interface."

“公共访问说明符表示该接口可以被任何包中的任何类使用。如果您不指定该接口是公共的,则您的接口将只能被定义在与该接口相同的包中的类访问。”

Is that what you want?

那是你要的吗?

回答by kdgregory

You class can use package protection and still implement an interface:

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

class Foo implements Runnable 
{
    public void run()
    {
    }
}

If you want some methods to be protected / package and others not, it sounds like your classes have more than one responsibility, and should be split into multiple.

如果您希望某些方法受到保护/打包而其他方法则不受保护,听起来您的类有不止一个职责,应该拆分为多个。

Edit after reading comments to this and other responses:

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

If your are somehow thinking that the visibility of a method affects the ability to invoke that method, think again. Without going to extremes, you cannot prevent someone from using reflection to identify your class' methods and invoke them. However, this is a non-issue: unless someone is trying to crack your code, they're not going to invoke random methods.

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

Instead, think of private / protected methods as defining a contract for subclasses, and use interfaces to define the contract with the outside world.

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

Oh, and to the person who decided my example should use K&R bracing: if it's specified in the Terms of Service, sure. Otherwise, can't you find anything better to do with your time?

哦,对于决定我的例子应该使用 K&R 支撑的人:如果它在服务条款中指定,当然。否则,你就不能找到更好的事情来利用你的时间吗?

回答by OscarRyz

Here's how it could be done using abstract classes.

下面是如何使用抽象类来完成它。

The only inconvenient is that it makes you "subclass".

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

As per the java guide, you should follow that advice "most" of the times, but I think in this situation it will be ok.

根据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()  );
    }
}

回答by Hash

I would just create an abstract class. There is no harm in it.

我只想创建一个抽象类。这没有什么坏处。

回答by Lawrence Dol

When I have butted up against this I use a package accessible inner or nested class to implement the interface, pushing the implemented method out of the public class.

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

Usually it's because I have a class with a specific public API which must implement something else to get it's job done (quite often because the something else was a callback disguised as an interface <grin>) - this happens a lot with things like Comparable. I don't want the public API polluted with the (forced public) interface implementation.

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

Hope this helps.

希望这可以帮助。

Also, if you truly want the methods accessed only by the package, you don't want the protected scope specifier, you want the default (omitted) scope specifier. Using protected will, of course, allow subclasses to see the methods.

此外,如果您真的想要仅由包访问的方法,您不需要受保护的范围说明符,而是需要默认(省略)范围说明符。当然,使用 protected 将允许子类看到这些方法。

BTW, I think that the reason interface methods are inferred to be public is because it is very much the exception to have an interface which is only implemented by classes in the same package; they are very much most often invoked by something in another package, which means they need to be public.

顺便说一句,我认为接口方法被推断为 public 的原因是因为拥有一个仅由同一包中的类实现的接口是非常例外的;它们最常被另一个包中的某些东西调用,这意味着它们需要公开。

回答by OscarRyz

This question is based on a wrong statement:

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

I know that an interface must be public

我知道接口必须是公共的

Not really, you can have interfaces with default access modifier.

并非如此,您可以拥有带有默认访问修饰符的接口。

The problem is I can't make the interface or the implemented methods protected

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

Here it is:

这里是:

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>

Hence, achieving what you wanted, prevent interface and class usage outside of the package.

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

回答by Jonas Eicher

With an interface you want to define methods that can be exposed by a variety of implementing classes. Having an interface with protected methods just wouldn't serve that purpose.

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

I am guessing your problem can be solved by redesigning your class hierarchy.

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

回答by Karl Giesing

Here's another solution, inspired by the C++ Pimpl idiom.

这是另一个解决方案,灵感来自 C++ Pimpl idiom。

If you want to implement an interface, but don't want that implementation to be public, you can create a composed object of an anonymous inner class that implements the interface.

如果您想实现一个接口,但不希望该实现是公开的,您可以创建一个实现该接口的匿名内部类的组合对象。

Here's an example. Let's say you have this interface:

这是一个例子。假设你有这个界面:

public interface Iface {
    public void doSomething();
}

You create an object of the Ifacetype, and put your implementation in there:

您创建一个该Iface类型的对象,并将您的实现放在那里:

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

Whenever you need to invoke doSomething(), you invoke it on your composed implobject.

每当您需要调用时doSomething(),您都可以在组合impl对象上调用它。

回答by siliconsmiley

I just came across this trying to build a protected method with the intention of it only being used in a test case. I wanted to delete test data that I had stuffed into a DB table. In any case I was inspired by @Karl Giesing's post. Unfortunately it did not work. I did figure a way to make it work using a protected inner class.

我刚刚在尝试构建一个受保护的方法时遇到了这个,目的是只在测试用例中使用它。我想删除我塞进数据库表的测试数据。无论如何,我的灵感来自@Karl Giesing帖子。不幸的是它没有奏效。我确实想出了一种使用受保护的内部类使其工作的方法。

The interface:

界面:

package foo;
interface SomeProtectedFoo {
    int doSomeFoo();
}

Then the inner class defined as protected in public class:

然后在公共类中定义为受保护的内部类:

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();
    }
}

You can then access the protected method only from other classes in the same package, as my test code was as show:

然后,您只能从同一包中的其他类访问受保护的方法,因为我的测试代码如下所示:

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

A little late for the original poster, but hey, I just found it. :D

原始海报有点晚了,但是嘿,我刚找到它。:D