Sal*_*RYS 431
这是我在JAVA中用来复制C++好友机制的一个小技巧.
让我们说我有一个班级Romeo和另一个班级Juliet.出于仇恨原因,他们在不同的包裹(家庭)中.
Romeo想要cuddle Juliet而且Juliet只想让Romeo cuddle她.
在C++中,Juliet将声明Romeo为(情人)friend但在java中没有这样的东西.
以下是课程和技巧:
女士优先 :
package capulet;
import montague.Romeo;
public class Juliet {
public static void cuddle(Romeo.Love love) {
Objects.requireNonNull(love);
System.out.println("O Romeo, Romeo, wherefore art thou Romeo?");
}
}
Run Code Online (Sandbox Code Playgroud)
所以方法Juliet.cuddle是,public但你需要Romeo.Love调用它.它使用它Romeo.Love作为"签名安全性"来确保只能Romeo调用此方法并简单地调用NullPointerException它,以便运行时将抛出一个nullif Romeo.Love.
现在男孩:
package montague;
import capulet.Juliet;
public class Romeo {
public static final class Love { private Love() {} }
private static final Love love = new Love();
public static void cuddleJuliet() {
Juliet.cuddle(love);
}
}
Run Code Online (Sandbox Code Playgroud)
该类private是公共的,但它的构造函数是Romeo.因此任何人都可以看到它,但只能Romeo.Love构建它.我使用静态引用,因此Romeo从未使用它只构造一次,不会影响优化.
因此,cuddle可Juliet Romeo.Love只有他能,因为只有他可以构建和访问一个Juliet实例,这是必需的cuddle,以NullPointerException她的(否则她会拍你一个Romeo).
Dav*_*d G 52
Java的设计者明确拒绝了朋友的想法,因为它在C++中有效.你把你的"朋友"放在同一个包里.私有,受保护和打包的安全性是语言设计的一部分.
James Gosling希望Java能够成为C++而不会出错.我相信他觉得朋友是个错误,因为它违反了OOP原则.包提供了一种合理的方式来组织组件而不会过于纯粹的OOP.
NR指出你可以使用反射作弊,但即使只有你没有使用SecurityManager才有效.如果打开Java标准安全性,除非您编写安全策略以明确允许,否则您将无法使用反射作弊.
Mat*_*och 44
"朋友"概念在Java中很有用,例如,将API与其实现分开.实现类通常需要访问API类内部,但这些不应该暴露给API客户端.这可以使用'Friend Accessor'模式实现,详情如下:
通过API公开的类:
package api;
public final class Exposed {
static {
// Declare classes in the implementation package as 'friends'
Accessor.setInstance(new AccessorImpl());
}
// Only accessible by 'friend' classes.
Exposed() {
}
// Only accessible by 'friend' classes.
void sayHello() {
System.out.println("Hello");
}
static final class AccessorImpl extends Accessor {
protected Exposed createExposed() {
return new Exposed();
}
protected void sayHello(Exposed exposed) {
exposed.sayHello();
}
}
}
Run Code Online (Sandbox Code Playgroud)
提供"朋友"功能的课程:
package impl;
public abstract class Accessor {
private static Accessor instance;
static Accessor getInstance() {
Accessor a = instance;
if (a != null) {
return a;
}
return createInstance();
}
private static Accessor createInstance() {
try {
Class.forName(Exposed.class.getName(), true,
Exposed.class.getClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
return instance;
}
public static void setInstance(Accessor accessor) {
if (instance != null) {
throw new IllegalStateException(
"Accessor instance already set");
}
instance = accessor;
}
protected abstract Exposed createExposed();
protected abstract void sayHello(Exposed exposed);
}
Run Code Online (Sandbox Code Playgroud)
来自'friend'实现包中的类的示例访问:
package impl;
public final class FriendlyAccessExample {
public static void main(String[] args) {
Accessor accessor = Accessor.getInstance();
Exposed exposed = accessor.createExposed();
accessor.sayHello(exposed);
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这是不可能的.
也许,你可以给我们一些关于你的设计的更多细节.像这样的问题可能是设计缺陷的结果.
考虑一下
| 归档时间: |
|
| 查看次数: |
73185 次 |
| 最近记录: |