Java 没有像 C++ 一样的友元。但是友元我认为是非常有用的。尤其是在设计 API 的时候,参见《Practical API Design》。友元可以帮助实现“clueless programming”(即无需考虑过多繁琐的细节就可以编程)。但是也容易被滥用。无论如何,我希望这个选择是在语言使用者手里。
《Practical API Design》里提到了一种 Accessor 模式,可以帮助 API 定义实现友元。但是这个并不是我们通常意义上的友元。因为它只能让客户端不能访问 API 的非 public 方法,但是 API 内部实现的任意部分都可以。更糟糕的是,它的实现复杂,而且需要自定义的运行时容器的配合。下面的方法非常短,而且可以指定一个友元类。灵感来源于 Accessor 模式。
package ydong.javatest;
import ydong.javatest.impl.TrueFriend;
public class Main {
public static void main(String[] args) throws Exception {
new TrueFriend().call();
}
private void onlyFriendCanCall(String msg) {
System.out.println("friend called: " + msg);
}
public abstract static class Friend {
public Friend() {
if (this.getClass() != friend) {
throw new UnsupportedOperationException();
}
}
private static final Class<? extends Friend> friend = TrueFriend.class;
protected final void onlyFriendCanCall(Main main, String msg) {
main.onlyFriendCanCall(msg);
}
}
}
Main 的 onlyFriendCanCall 方法要求只能被 TrueFriend 类调用。原理就是利用内部类可以访问外部类的私有成员来将友元问题转换成父类识别子类类型的问题。
package ydong.javatest.impl;
import ydong.javatest.Main;
public final class TrueFriend extends Main.Friend {
public void call() {
this.onlyFriendCanCall(new Main(), "TrueFriend");
}
}
TrueFriend 不需要跟 Main 在同一个包下面。它只要继承 Main.Friend 就可以访问到 Main.Friend.onlyFriendCanCall 方法。继而间接地访问到 Main.onlyFriendCanCall。为什么要用继承?因为继承可以让 Main.Friend 拿到实际调用者--TrueFriend 的类型,进而去判断是否是友元类。普通的方法调用如果不用类似 AOP 的机制是没有办法拿到这个信息的。你可以写一个 FalseFriend 来试试看效果?
Friend 的代码非常短,可以直接背下来了。用的时候只要记得原理可以很快写出来。你可以将其扩展成指定哪些方法可以被哪些友元类(可以是多个)调用。
这个方法有个明显的缺点:如果目标友元类已经继承了某个类就不行了。虽说是从南墙撞到了北墙,不过这个方法已经可以解决很多问题了。很多情况下你可以想办法调整设计使得目标友元类没有其它父类。至少在我的项目里可以做到。如果有人找到了更好的方法请一定要告诉我。
虽然文章放在设计模式的类目下面,但是我并不确定这个是否真的是模式。就算是也不知道该叫什么。
分享到:
相关推荐
关于c+模板之友元类友元函数的实例化,图形界面之矩形。
本文档详细介绍了C++友元函数及友元类,方便大家对比学习
友元函数,类外普通函数声明为类的友元,之后即可与类共享数据
③ 对于友元成员和友元类两种实现方式,可以另外定义一个求解两点距离的ComputeDistance类,将distance()作为该类的成员函数; ④ 设计main()测试函数,并准备好合适的测试数据。 (3)程序调试运行 运行程序查看...
友元成员,A类中的成员函数f声明为B为的友元,此时函数f就称为友元成员
让你很好的理解C++友元接口问题。加油,让我们一起冲刺C++。
友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。类授予它的友元特别的访问权。通常同一个开发者会出于技术和非技术的原因,控制类的友元和成员函数(否则当你想更新你的类时,还要征得其它部分的拥有...
友元是一种类与类外数据共享的机制,包括友元函数、友元成员、友元类三种
主要讲解c++种的友元类友元函数 可以更好地学习其中的内容 友元在类中担任着十分关键的角色 所以更应该认真学习
实例讲解C++友元,利用实例讲解C++友元的知识
私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦。
各种友元应用举例。欢迎大家下载使用。 各种友元应用举例。欢迎大家下载使用。
数据共享与友元的使用
运算符单例友元重载作业,不理解的可以模仿学习。
简单的友元类,简单的测试了友元函数与友元类,属于概念性的测试
类域 友元 运算符 重载类域 友元 运算符 重载类域 友元 运算符 重载
如何声明和创建友元类 简单友元类的声明,C++中友元类的应用范围
用vc++友元类程序的编写。程序用vc++6.0开发,其中关于年月份的判断相对前面,程序简单易懂。
C++友元习题.pdf
我们知道,基类的private成员在派生类中不能被访问。那么,友元函数能否继承。(举例说明)