Java 是否有某种方法将对对象成员的访问限制为仅对通过组合拥有它的对象的访问?

Java 是否有某种方法将对对象成员的访问限制为仅对通过组合拥有它的对象的访问?,java,oop,design-patterns,composition,class-visibility,Java,Oop,Design Patterns,Composition,Class Visibility,我真的觉得一定有办法解决这个问题 假设我有大量对象作为所有者类的组件。我想为其成员提供对该所有者类的客户端的轻松访问,因此我将所有这些对象公开。每个对象的所有成员都是公共的。但组件的一个成员不应仅由其所有者自己访问其所有者的客户端: public class ComponentObject { public int int_field; public float float_field; public Object object_field; public Ob

我真的觉得一定有办法解决这个问题

假设我有大量对象作为所有者类的组件。我想为其成员提供对该所有者类的客户端的轻松访问,因此我将所有这些对象公开。每个对象的所有成员都是公共的。但组件的一个成员不应仅由其所有者自己访问其所有者的客户端:

public class ComponentObject
{
    public int int_field;
    public float float_field;
    public Object object_field;

    public Object public_method1()
    {
        //something;
    }

    public Object public_method2()
    {
        //something;
    }

    public Object restricted_to_owner_only()
    {
        //something;
    }
}

//all clients of Owner should be able to access all the members of its components, except
//restricted_to_owner_only, which only Owner should be able to access
public class Owner
{
    public ComponentObject component1;
    public ComponentObject component2;
    public ComponentObject component3;
    //... lots of others
    public ComponentObject component300;
}
有没有办法做到这一点?请注意,任何包中的任何类都可以拥有一个
ComponentObject
,因此在
restricted\u to\u owner\u
中使用包级别的可见性似乎不是一个选项
ComponentObject
类似于一个实用程序类,可在其他应用程序中重用

也许有一个注释在编译时在一些很好的库中实现了这一点

编辑:我忘了提到ComponentObject在现实生活中是一种参数化类型,Owner中的每个字段的参数化方式都不同。我试图把细节抽象出来,这样我们就可以专注于设计问题本身,但我抽象得太多了。我将发布一些更类似于真实问题的东西:

public class ComponentObject<T>
{
    public int int_field;
    public float float_field;
    public T object_field;

    //any method could return T or take T as an argument.
    public T public_method1()
    {
        //something;
    }

    public Object public_method2()
    {
        //something;
    }

    public Object restricted_to_owner_only()
    {
        //something;
    }
}

//all clients of Owner should be able to access all the members of its components, except
//restricted_to_owner_only, which only Owner should be able to access
public class Owner
{
    public ComponentObject<String> component1;
    public ComponentObject<File> component2;
    public ComponentObject<Consumer<Boolean>> component3;
    //... lots of others
    public ComponentObject<Integer> component300;
}
公共类组件对象
{
公共整数域;
公共浮球场;
公共T对象_字段;
//任何方法都可以返回T或将T作为参数。
公共T公共_方法1()
{
//某物;
}
公共对象public_method2()
{
//某物;
}
公共对象仅限于所有者()
{
//某物;
}
}
//所有者的所有客户端都应该能够访问其组件的所有成员,除了
//仅限于所有者,只有所有者才能访问该所有者
公共类所有者
{
公共组件对象组件1;
公共组件对象组件2;
公共组件对象组件3;
//…还有很多
公共组件Object组件300;
}
编辑2(可能是一个解决方案):伙计们,受罗密欧和朱丽叶爱情的启发,我写了这个解决方案,你们能找出它的缺点吗?或者它会像我想的那样工作吗

//add this class
public class OwnershipToken
{
    private static int id_gen = 0;
    public final int id = id_gen++;

    @Override
    public boolean equals(Object obj)
    {
        return (obj instanceof OwnershipToken) && ((OwnershipToken)obj).id == id;
    }

    @Override
    public int hashCode()
    {
        return id;
    }
}

//Then change this in ComponentObject<T>:
public class ComponentObject<T>
{
    //add this field:
    private final OwnershipToken ownershipToken;

    //add this constructor
    public ComponentObject(OwnershipToken onwershipToken)
    {
        this.ownershipToken = ownershipToken;
    }

    //change restricted_to_owner_only signature:
    public Object restricted_to_owner_only(OwnershipToken ownershipToken)
    {
        //add this condition
        if(this.ownershipToken.equals(ownershipToken)
            //something;
    }
}

//finally, Owner gains a field:
public class Owner
{
    private final OwnershipToken ownershipToken = new OwnershipToken();
    //... etc, remainder of the class
}
//添加此类
公共类所有权
{
私有静态int id_gen=0;
公共最终整数id=id_gen++;
@凌驾
公共布尔等于(对象obj)
{
return(OwnershipToken的obj实例)和&((OwnershipToken)obj.id==id;
}
@凌驾
公共int hashCode()
{
返回id;
}
}
//然后在ComponentObject中更改此选项:
公共类组件对象
{
//添加此字段:
私人最终所有权所有权所有权;
//添加此构造函数
公共组件对象(OwnershipToken onwershipToken)
{
this.ownershipToken=ownershipToken;
}
//将受限签名更改为仅所有者签名:
公共对象仅限于所有者(OwnershipToken OwnershipToken)
{
//添加此条件
如果(此ownershipToken.等于(ownershipToken)
//某物;
}
}
//最后,所有者获得一个字段:
公共类所有者
{
私有最终所有权token OwnershipToken=新所有权token();
//…等等,这门课的剩余部分
}

这能按预期工作吗?

我知道你想要什么,我认为这是不可能的。
//add this class
public class OwnershipToken
{
    private static int id_gen = 0;
    public final int id = id_gen++;

    @Override
    public boolean equals(Object obj)
    {
        return (obj instanceof OwnershipToken) && ((OwnershipToken)obj).id == id;
    }

    @Override
    public int hashCode()
    {
        return id;
    }
}

//Then change this in ComponentObject<T>:
public class ComponentObject<T>
{
    //add this field:
    private final OwnershipToken ownershipToken;

    //add this constructor
    public ComponentObject(OwnershipToken onwershipToken)
    {
        this.ownershipToken = ownershipToken;
    }

    //change restricted_to_owner_only signature:
    public Object restricted_to_owner_only(OwnershipToken ownershipToken)
    {
        //add this condition
        if(this.ownershipToken.equals(ownershipToken)
            //something;
    }
}

//finally, Owner gains a field:
public class Owner
{
    private final OwnershipToken ownershipToken = new OwnershipToken();
    //... etc, remainder of the class
}
但是,仍然有一种方法可以做到这一点

在owner类中创建一个id:

private int id = new Random().nextInt(10000);
在ComponentObject中:

private id;

public ComponentObject(int id){
    this.id = id;
}

public Object restricted(int id){
    if(this.id != id)
        return null;
    else
        return object;
}
所有者:

private ComponentObject<String> string;

public Owner() {
    string = new ComponentObject<>(id);
    string.restricted(id);
    //if the id is right it will return the restricted object, if not i will                
    //return null   
私有组件对象字符串;
公共所有者(){
字符串=新的ComponentObject(id);
string.restricted(id);
//如果id是正确的,它将返回受限对象,如果不是,我将返回
//返回空值

}

那么,假设你有对象A,它有字段B、C和D,你想让其他人能够使用B、C和D,但它们的方法应该只能用于A?我不想说它是重复的,但这听起来像是朋友的概念:@Compass这个优雅的shakesperian解决方案可能给了我一个主意。这将是一个好主意d解决方案,问题是我想我的问题不够清楚,让我通过编辑来解决。但是正如你所看到的,一个
所有者可以有很多
组件对象
,每个组件对象都以不同的方式参数化与另一个关于Java中缺少
friend
access修饰符的问题类似,您是否愿意尝试我的解决方案?