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 的代码非常短,可以直接背下来了。用的时候只要记得原理可以很快写出来。你可以将其扩展成指定哪些方法可以被哪些友元类(可以是多个)调用。
这个方法有个明显的缺点:如果目标友元类已经继承了某个类就不行了。虽说是从南墙撞到了北墙,不过这个方法已经可以解决很多问题了。很多情况下你可以想办法调整设计使得目标友元类没有其它父类。至少在我的项目里可以做到。如果有人找到了更好的方法请一定要告诉我。
虽然文章放在设计模式的类目下面,但是我并不确定这个是否真的是模式。就算是也不知道该叫什么。
分享到:
相关推荐
标题"友元函数和友元类"涉及到两个核心概念:友元函数和友元类。 **友元函数** 是一个非成员函数,但它被声明为某个类的友元,这意味着它可以直接访问该类的私有和受保护成员。友元函数不是类的成员,因此它们不在...
下面是一些关于友元函数的关键点: - **友元函数的参数**:由于友元函数没有`this`指针,因此当需要访问非静态成员时,通常需要传入对象作为参数。 - **友元函数的位置**:友元函数的声明可以放在类的私有部分或...
下面我们将深入探讨这三个概念及其工作原理。 首先,**友元类**(Friend Class)是指在一个类的定义中声明的另一个类,被声明为友元的类可以访问该类的私有(private)和保护(protected)成员。这种关系是非对称的...
在C++编程语言中,友元(Friend)是一种特殊的机制,允许类的私有和保护成员被非成员函数或者另一个类的成员函数直接访问。友元的使用旨在解决数据隐藏和效率之间的矛盾,但同时也可能影响到代码的封装性和可维护性...
### C++友元接口详解 在C++编程语言中,友元(Friend)是一个非常重要的概念,它允许非成员函数或类访问另一个类的私有(private)和受保护(protected)成员。本文将深入探讨C++中的友元机制,并通过具体的代码...
友元函数是C++语言中一个重要的概念,它突破了面向对象编程中类成员访问的封装性,允许某些外部函数或者类访问当前类的私有成员和保护成员。在实际开发中,合理使用友元函数可以优化代码结构,简化某些操作,但同时...
在C++编程语言中,"友元"(friend)是一个重要的特性,它允许类或函数访问其他类的私有(private)和保护(protected)成员。这个概念打破了封装的常规,为了解决某些特定问题提供了便利。在这个实例讲解中,我们将...
关于c+模板之友元类友元函数的实例化,图形界面之矩形。
在C++编程语言中,友元机制是一种打破封装性的特性,允许一个类访问另一个类的私有或受保护成员。这种机制在某些情况下是必要的,比如处理关联对象间的操作,或者实现特定的数据结构。本篇文章将详细讲解如何在VC++...
"C++友元习题.pdf" 本摘要信息涵盖了C++语言中友元函数的使用方法和应用场景,通过三个实例程序,详细说明了友元函数的声明、定义和使用。 知识点1:友元函数的声明和定义 在C++中,友元函数是指在类外部定义的...
友元函数和友元类的需要:类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又...
在C++程序设计中,友元(Friend)是一种特殊的机制,允许一个类访问另一个类的私有(private)和保护(protected)成员,打破了封装的限制。本篇将深入探讨友元的概念、分类以及如何使用,同时通过实例代码进行详细...
友元类的使用 C++ 友元类(Friend Class)是一种特殊的类关系,在 C++ 编程语言中广泛应用于实现复杂的对象交互。友元类可以访问其他类的私有成员,实现紧耦合的对象关系。 在本例中,我们定义了两个类:Time 和 ...
下面是一个简单的例子,展示了如何在MFC中使用友元类: ```cpp class MyApplication : public CWinApp { // ... friend class MyDialog; int m_secretData; }; class MyDialog : public CDialog { public: ...
在C++编程语言中,友元机制是一种打破封装性的特性,允许一个类访问另一个类的私有或受保护成员。这种关系是通过友元声明来建立的,它为类之间的协作提供了一种灵活的方式,尤其是在设计复杂的软件结构时。本教程将...
友元函数,类外普通函数声明为类的友元,之后即可与类共享数据
下面我们将详细探讨全局友元类的实现以及它在C++程序设计中的应用。 首先,我们来看标题“c++ demo,全局友元类的实现”。这里的“demo”意味着我们将通过一个实例来理解这个概念。全局友元类不同于普通友元类,...
③ 对于友元成员和友元类两种实现方式,可以另外定义一个求解两点距离的ComputeDistance类,将distance()作为该类的成员函数; ④ 设计main()测试函数,并准备好合适的测试数据。 (3)程序调试运行 运行程序查看...
友元成员,A类中的成员函数f声明为B为的友元,此时函数f就称为友元成员
在编程领域,运算符单例友元重载是一种高级技巧,它涉及到面向对象设计模式、类的内部工作原理以及C++中的友元函数和运算符重载。让我们深入探讨这些概念,以便更好地理解和应用。 首先,我们要理解什么是“单例...