【问题标题】:Class-specific method visibility特定于类的方法可见性
【发布时间】:2014-07-20 05:37:53
【问题描述】:

有没有一些面向对象的东西,你可以从某些类中调用一些方法,但不是全部?有没有类似protected的东西?

假设您有一个方法void foo(),并且您希望程序员可以在几个类型 类中使用它(可能类似于使用类型变量(指定:T type)。现在,也许有什么方法可以在不继承带有foo() 的类或创建接口的情况下指定哪些类或类的类型可以访问该方法?

我猜这可能类似于多重继承和多态性?但是我仍然希望只有类和某些类可以访问该方法而不改变该方法的可见性。我希望可见性是特定于类的。

这是一个例子:

class Afoo() 视为私有,但只有该类将其视为私有。
class Bfoo() 视为公共/受保护,但只有该类将其视为公共。

方法类型为default

我想更容易问和回答的是:“是否存在特定于类的可见性?”

【问题讨论】:

标签: java visibility access-specifier


【解决方案1】:

在 C++ 中有类似您要求的东西,它被称为 friend classes。然而,Java 不支持该概念:

'Friends' equivalent for Java?

第二种选择是使用代码反射来访问类私有成员,但这不是一个干净的解决方案,仅适用于protected 元素:

public class C1 {

    public C1()
    {
        x = "Hello Word!";
    }

    protected String x;
}

在不同类的方法上:

String val = (String)obj.getClass().getDeclaredField("x").get(obj);
System.out.println("val: " + val);

编辑:经过一些研究,我发现甚至可以访问私人成员:

Field field = obj.getClass().getDeclaredField("x");
field.setAccessible(true);
String val = (String)field.get(obj);
field.setAccessible(false);

【讨论】:

  • 坦率地说,我很高兴 Java 没有友元类。真是一团糟。
  • 如果我的 DynamicWindow 和 Debugger 是 friends... 那么我实际上可以让这个 GraphicsOptimizedThreadedOeuvre 正常工作!
  • 或者也许你可以为方法的访问者指定一个 jvm 参数?话又说回来,可以制作一个包含朋友的非官方 Java 版本,或者也许...... JNI?也许可以有朋友的.cpp文件可以使它成为可能。但这似乎是一个大项目,只是为了设置知名度......
  • @JonSkeet 我的回答如你所说,无法按照 OP 的要求授予访问权限,但我试图给他另一种方法来获得他需要的东西。我本可以说“不可能”完成它,但在这里我们将分享我们关于问题解决方案的观点或观点。很抱歉你认为它不值得被接受。
  • @PabloFranciscoPérezHidalgo:更多的是将大部分空间用于反射部分,这似乎并不相关。不想声称我的答案应该被接受,我会说我的答案至少提供了限制对 some 类的可见性的替代方案 - 事实证明它不符合 OP 的需求,但我个人认为它比反射部分更接近于给出一个选项。不过问题不大……
【解决方案2】:

不,Java 中没有类似的东西。

您最接近的是将类放在同一个包中,此时它们可以访问任何未指定 any 访问修饰符的成员。但是你不能指定特定的类。

另一个适合一些情况的选择是使用嵌套类:

class Outer {
    private static class Inner {
    }
}

这里OuterInner 可以访问彼此的私人成员。

【讨论】:

  • 嗯,这当然是一种可能性,但与朋友一起......这不适合我正在从事的项目。这些类完全彼此独立,并且使用此 Oeuvre 的类不应该知道关于对象的任何事情,除了创建它们的实例......除非我创建了一些类存储对象,但这将是多余且低效的……为什么要复制变量?它已经被存储/初始化过一次。
  • @LinkTheProgrammer:我不太确定我是否遵循了你的例子(你没有真正给我们足够的背景信息)但基本上,答案是“不”。
【解决方案3】:

访问级别

Modifier    Class   Package Subclass  World
public       Y        Y       Y        Y
protected    Y        Y       Y        N
no modifier  Y        Y       N        N
private      Y        N       N        N

thats your lot, there are not any other access modifiers.

【讨论】:

  • 次要问题,但我会从 default 中删除降价,只是为了清楚说明它没有像其他三个一样明确用于修改访问权限
  • default 在 Java 文档中通常称为 package-privatedocs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
  • 这可能是一个问题中的一个问题,但是,默认变量是包私有的,还是只能从超级包访问子包默认对象?
【解决方案4】:

只要花点功夫,你就可以让一个班级看起来像是两个不同的班级:

// An interface.
interface A {
    public void a ();
}

// Another interface.
interface B {
    public void b ();
}

// Deliberately NOT stating we implement either A or B but actually we implement both.
class C {
    public void a () {

    }
    public void b () {

    }
}

// Pick either implementation from C and tell the world about it.
class D extends C implements A {
    // Do nothing - already done by C.
}

class E extends C implements B {
    // Do nothing - already done by C.
}

public void test() {
    A d = new D();
    B e = new E();
}

这里的DE 实际上是功能相同的对象,因为它们实际上都是Cs。但是,在创建它们时,它们看起来像是 AB,它们是两个不同的接口。

不幸的是,我们无法隐藏这样一个事实,即它们都扩展了 C,但更进一步的花招,我们也可以使用工厂来做到这一点。

// Hide the guts of it all in a factory.
static class Factory {
    // Make sure you MUST use the factory methods.
    private Factory () {

    }

    // Construct an A.
    public static A newA () {
        return new D();
    }

    // Construct a B.
    public static B newB () {
        return new E();
    }
}

【讨论】:

  • 嗯,没有接口......这本作品应该为程序员做工作,而不是为程序员做更多的工作
猜你喜欢
  • 2014-01-13
  • 2012-02-18
  • 2012-11-07
  • 1970-01-01
  • 1970-01-01
  • 2014-08-11
  • 2010-09-25
  • 2011-01-14
  • 1970-01-01
相关资源
最近更新 更多