0
Class A {
   String x;
}

I have 2 interfaces I1 and I2.

Class C1 implements I1

Class C2 implements I2

Is there any way to only allow Class C2 to update x of Class A? i.e. is there any way by which classes implementing a particular interface update the members of Class A?

Classes implementing I1 should only be able to read the members of class A and they should not be allowed to update the members of class A.

martin
  • 49
  • 2
  • 10
  • 5
    It would be interesting to know the design process that lead to this necessity. – Federico klez Culloca Nov 12 '19 at 11:53
  • 1
    Does this answer your question? [Java: How to limit access of a method to a specific class?](https://stackoverflow.com/questions/11549394/java-how-to-limit-access-of-a-method-to-a-specific-class) – Guy Nov 12 '19 at 11:53
  • 1
    I doubt you really want to do this. This kind of sounds like an underlying design issue. – Marcel Nov 12 '19 at 12:04
  • @Federico I am creating a platform which has multiple independent components. It need classes implementing a particular interface to only update global variable list and other classes should not be able to modify it – martin Nov 12 '19 at 12:15

3 Answers3

3

Although it seems like a design fault, but You can still achieve it by using instanceof in setter and getter of x:

class A {
    private String x;

    public void setX(String value, Object obj){
        if(obj instanceof I2){
            this.x = value;
        }
    }

    public String getX(Object obj){
        if(obj instanceof I2){
            return this.x;
        }else{
            return null;
        }
    }
}

USAGE:

A a = new A();
a.setX("ABC",this);
a.getX(this);
Mustahsan
  • 3,852
  • 1
  • 18
  • 34
1

For an independent interface only solution one just has:

class A {
    private String x;

    public void setX(AUser u, String x) {
        if (u != null) { this.x = x; }
    }
}

interface AUser {
}
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • It will require passing interface to function argument explicitly – martin Nov 12 '19 at 12:18
  • @myst In the interface `default setX(A a, String x) {...}` would have the same problem. Only with A creating an implementation of the/an interface there would be some exploitable reference between the two objecs. – Joop Eggen Nov 12 '19 at 12:43
1

I could see there are multiple checks that you will have to implement.

  1. State of the object should be immutable when referenced using getter method. For e.g. if your getter method is returning object or collection, it shouldn't be modifiable. Otherwise whatever protection you provide at setter level can be defeated very easily.

  2. Try to segregate authorization constraint from actual object. Possibly use Proxy pattern.

  3. Use StackTraceElement to identify calling class/method. Can be derived using Thread.currentThread().getStackTrace(). This also protects your code from deceiving setter method by passing instance of authorised class.

On the whole, whether it's design flaw or necessity, if you decide in future to rectify this, you will be able to do that without leaving any footprints. The calling programs, won't have to undergo a change.

CuriousMind
  • 3,143
  • 3
  • 29
  • 54
  • Are there any drawbacks of using Thread.currentThread().getStackTrace() or throwable.getStackTrace()? – martin Nov 13 '19 at 07:38
  • As of now, I don't see any drawbacks. But it would be appropriate to use ThreadStack Trace rather than Throwable stacktrace. Though both of them result into same object, exception introduces unnecessary boilerplate code and just doesn't feel right. Another heads-up, if your code allows extension (no possibility of introducing interceptors or AspectJ like stuffs) you may have to walk the entire stack, otherwise just referring to the top most element is sufficient. – CuriousMind Nov 13 '19 at 14:12