Есть ли способ ограничить доступ к элементу объекта только объектом, которому он принадлежит по составу?

Я действительно чувствую, что должен быть способ обойти это.

Представьте, что у меня есть большое количество объектов в качестве компонентов класса владельца. Я хочу предложить легкий доступ к клиентам этого класса-владельца его членам, поэтому я делаю все эти объекты общедоступными. Каждый из этих объектов также имеет всех своих участников. Но один элемент компонентов не должен быть доступен для клиентов их владельца, только самим их владельцем:

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_to_owner_only кажется, не вариант. 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;
}

РЕДАКТИРОВАТЬ 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
}

будет ли это работать как задумано?

1 ответ

Я понимаю, что вы хотите, и это невозможно, я думаю. Но есть еще один способ сделать это!

Сделать идентификатор в классе владельца:

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   

}

Другие вопросы по тегам