Ala*_*ody 29
Java没有来自C++的friend关键字.然而,有一种方法可以效仿; 这种方式实际上可以提供更精确的控制.假设您有A类和B类.B需要访问A中的某些私有方法或字段.
public class A {
private int privateInt = 31415;
public class SomePrivateMethods {
public int getSomethingPrivate() { return privateInt; }
private SomePrivateMethods() { } // no public constructor
}
public void giveKeyTo(B other) {
other.receiveKey(new SomePrivateMethods());
}
}
public class B {
private A.SomePrivateMethods key;
public void receiveKey(A.SomePrivateMethods key) {
this.key = key;
}
public void usageExample() {
A anA = new A();
// int foo = anA.privateInt; // doesn't work, not accessible
anA.giveKeyTo(this);
int fii = key.getSomethingPrivate();
System.out.println(fii);
}
}
Run Code Online (Sandbox Code Playgroud)
usageExample()显示了它的工作原理.B的实例无法访问A实例的私有字段或方法.但是通过调用giveKeyTo(),B类可以获得访问权限.没有其他类可以访问该方法,因为它需要有效的B作为参数.构造函数是私有的.
然后,B类可以使用在密钥中传递给它的任何方法.虽然设置比C++好友关键字更笨拙,但它更精细.A类可以准确选择哪些方法可以准确地公开哪些类.
现在,在上面的例子中,A授予对B的所有实例和B的子类实例的访问权.如果后者不合适,那么giveKeyTo()方法可以在内部用getClass()检查其他实际的类型,并抛出如果它不是精确的B则是例外.
假设A.foo()只应该被调用B.这可以通过只能由其生成的令牌来安排B.
public class B
{
public static class ToA { private ToA(){} }
private static final ToA b2a = new ToA();
void test()
{
new A().foo(b2a);
}
}
public class A
{
public void foo(B.ToA b2a)
{
if(b2a==null)
throw new Error("you ain't B");
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
只能B生成非空B.ToA令牌.如果同时A和B不泄露此令牌的第三方,没有其他人可以调用A.foo()
如果也A2想要朋友B,则需要不同的令牌类型.如果是同样的类型,因为A得到了来自类型的令牌B,A可以假装是B来A2.
检查是在运行时完成的,而不是编译时间,这并不完美.虽然没什么大不了的,因为任何第三方只能A.foo()用a 来调用null,它不能是我们想要在编译时检查的无辜错误; 它可能是恶意的,所以我们不关心在编译时警告调用者.
| 归档时间: |
|
| 查看次数: |
40889 次 |
| 最近记录: |