-1

I really feel like there must be a way around this.

Imagine I have a large number of objects as components of an owner class. I want to offer easy access to the clients of this owner class to its members, so I make all those objects public. Each of those objects also have all their members public. But one member of the components should not be accessible to the clients of their owner, only by their owner itself:

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

Is there a way to achieve this? Note that any class from any package can own a ComponentObject, so using package level visibility at restricted_to_owner_only doesn't seem to be an option. ComponentObject is like a utility class, reusable in other applications.

Maybe there's an annotation that enforces that at compile time in some nice lib out there?

EDIT: I forgot to mention that ComponentObject is a parameterized type in real life, and each field in Owner is parameterized differently. I tried to abstract off the details so we could focus on the design problem itself, but I abstracted too much. I will post bellow something more similar to the real problem:

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

EDIT 2 (Possibly a solution): Guys, inspired by Romeo and Juliet's love, I wrote this solution, can you spot any faults with it? Or would it work as I intended?

//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
}

would this work as intended?

FinnTheHuman
  • 1,115
  • 13
  • 29
  • So, lets say you have object A, and it has the fields B, C and D, and you want to make others be able to the B, C and D, but the methods of them should only be accessible for A? – Bálint Oct 27 '16 at 16:03
  • 1
    http://stackoverflow.com/questions/182278/is-there-a-way-to-simulate-the-c-friend-concept-in-java – Alexander Anikin Oct 27 '16 at 16:03
  • 1
    I don't want to say it's a duplicate, but this sounds like the friend concept: http://stackoverflow.com/questions/182278/is-there-a-way-to-simulate-the-c-friend-concept-in-java – Compass Oct 27 '16 at 16:03
  • @Compass This elegant shakesperian solution may have given me an idea. – FinnTheHuman Oct 27 '16 at 16:33

1 Answers1

1

I understand what you want and that is impossible i think. But, there is still one way to do it!

Make an id in the owner class:

private int id = new Random().nextInt(10000);

In ComponentObject:

private id;

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

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

In owner:

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   

}

Joza100
  • 338
  • 4
  • 16
  • This would be a good solution, the problem is I wans't clear enough in my question, let me fix that by editing it. – FinnTheHuman Oct 27 '16 at 16:18
  • But as you can see, one `Owner` can have a lot of `ComponentObjects`, each of them parameterized in a different way. – FinnTheHuman Oct 27 '16 at 16:44
  • try my solution – Joza100 Oct 27 '16 at 17:06
  • Yes, I edited my question inspired by the comments 2 users posted on it, pointing out how it was somewhat similar to another question regarding the lack of `friend` access modifier in Java – FinnTheHuman Oct 27 '16 at 17:07
  • would you like to try my solution anyways? – Joza100 Oct 27 '16 at 17:09
  • Yes, your solution is basically the same, I just don't use `Random` but serial ids instead, and I use an object instead of a raw integer, to provide some scalability in case I need something else from the `OwnershipToken` class later in the project. I'm just not absolutely sure it's bullet proof. – FinnTheHuman Oct 27 '16 at 17:09