【问题标题】:Implementing friend (available in C++) functionality in Java [duplicate]在 Java 中实现朋友(在 C++ 中可用)功能 [重复]
【发布时间】:2010-10-11 12:47:09
【问题描述】:

好吧,让我们离开关于友谊是否打破封装的争论,并实际尝试优雅地提出一个连贯的设计。这是一个双重功能:

1) 关于如何实施的一般问题:

   public class A 
   {
      friend class B;
   }

2) 为什么我需要这个功能?我的一些类实现了 Serializable 接口。但是,我想在 Derived 类中保护 Serializable 方法,这样我就不会将它们暴露给客户端(以及文档——javadoc)。但是,内部类应该能够访问它们。在java中解决这个问题的一般方法是什么?

注意:我使用的是当前 C++ 标准中定义的友谊。

谢谢

【问题讨论】:

  • Java 是否支持像 C# 一样的“内部”修饰符?在 C# 中,您可以使用 internal 使内容仅在同一程序集中可见。
  • 信息确实不够。无论如何,可序列化方法不应该是私有的。
  • 是的,您不需要访问序列化方法来序列化对象。这似乎是有争议的,也不是问题……
  • @OregonGhost:不,Java 不支持。最接近的等价物是默认访问修饰符,它使类或成员对定义它的包可见。 (Java 中的包最类似于 C# 中的命名空间。)
  • JDK7 可能(也可能没有)具有模块访问说明符。这将与内部不同,因为它不依赖于部署单元。

标签: java javadoc


【解决方案1】:

一般的解决方案是使方法包私有(这是 Java 中的默认保护级别)。这样同一个包中的任何代码都可以访问它们,但不能访问外部代码。

Java 不允许与特定外部类任意共享方法。

编辑:受保护的成员实际上较少私有而不是包私有。如果您有受保护的成员,您可以从包外的派生类和包内的任何类访问它们。所以这可能是您问题的解决方案 - 在您要导出到的包中的另一个类中派生该类。

一般来说,Java 将包视为封装的主要模块。 public/protected 接口用于包外的类,默认保护级别允许包内访问。

【讨论】:

  • 好吧,我也需要从其他内部包中访问它们:(
  • 包私有(默认访问)对于除了顶级类型之外的任何东西都应该很少见。
  • @Tom:我同意。我只是指出,这是唯一得到官方认可的分享内部信息的方式。
【解决方案2】:

好像你想要一个外观。

您似乎有一个类需要公开访问实现中涉及的各种其他类(即使在不同的包中)。但您不希望客户有权访问。

因此,让实现变得尽可能复杂。有一个外观类,只有你想要的接口,委托给实现。

【讨论】:

    【解决方案3】:

    此链接提供了一种在 Java 中模拟朋友访问的方法:http://macchiato.com/columns/Durable7.html

    从链接复制的代码(以防网站无法访问):

    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);
    }
    }
    

    【讨论】:

      【解决方案4】:

      我注意到一件事……听起来您不希望必须重写的方法,因为您正在实现 Serializable 以公开。不过有一件事,Serializable 是一个标记接口(它不提供要覆盖的方法),并且 readObject 和 writeObject 方法应该是私有的。

      我错过了什么吗?

      【讨论】:

        【解决方案5】:

        您的问题有两种解决方案,它们不涉及将所有类保存在同一个包中。

        第一种是使用(Practical API Design, Tulach 2008)中描述的 Friend Accessor/Friend Package 模式。

        第二个是使用OSGi。有一篇文章here 解释了 OSGi 是如何做到这一点的。

        相关问题:1234

        【讨论】:

          猜你喜欢
          • 2010-10-11
          • 1970-01-01
          • 1970-01-01
          • 2011-09-24
          • 1970-01-01
          • 2010-10-06
          • 1970-01-01
          • 2019-07-01
          相关资源
          最近更新 更多