Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict Access of method calling in Java

I have a class A. This class contains two methods let say method1() and method2(). Now I have two other classes named B and C. Both classed will contain the same instance of A class.

Now I want to restrict access in such a way that my 'Bclass can only callmethod1()and my otherC' class can call method2(). The design scheme is as follow-

class A {
    void method1(){/*-------------*/}
    void method2(){/*-------------*/}
}

now if I create an instance of A and share it with my B and C class

class B {
    A ob;
    public B(A ob) {
        this.ob=ob;
    }
    public void process() {
        ob.method1(); //only call method1()
        ob.method2(); //can't access it.
    }
}

class C {
    A ob;
    public C(A ob) {
        this.ob=ob;
    }
    public void process() {
        ob.method2(); //only call method2()
        ob.method1(); //can't access it.
    }
}
like image 658
Subhabrata Mondal Avatar asked Aug 02 '17 06:08

Subhabrata Mondal


2 Answers

Simple: you can't.

In contrast to the "friend" concept in C++, you can only change visibility for all other classes.

In other words: in Java, you are stuck with package protected, protected, private and public. No "private for B" and "public for C".

Of course, you could do very strange things, like a method analyzing its own stack trace, and throwing exceptions if it finds to be called by the "wrong" class. But doing so is most likely bad practice.

In that sense, the real answer is: step back and have a close look at the functionality behind those two methods. If you really think these functions need different visibility - then chances are that they should not be in the same class in the first place! Because they probably implement two very different responsibilities - and well, any class, method, ... should have exactly one single responsibility.

The closest you can get to is the suggestion by smosel: your class implements different interfaces, and you make sure that clients are using your class through the "interface" interface - then they are restricted in the methods they can call. But of course - a client can easily cast the interface reference into a class reference and call the other methods then.

Given the comments: alone the used names indicate the above point: when A is a ConfigurationLoader - why does it contain a method to check a configuration? A ConfigurationLoader should load the configuration (to be triggered by class C) - and the result of that operation would be a "configuration" object - and class B would then work with that configuration object (instead of interacting with the loader).

like image 117
GhostCat Avatar answered Oct 12 '22 22:10

GhostCat


One solution is to move each method into its own interface, and have A implement both interfaces:

interface A1 {
    void method1();
}

interface A2 {
    void method2();
}

class A implements A1, A2 {
    @Override public void method1() {}
    @Override public void method2() {}
}

Now you can pass the same object as A1 to B and as A2 to C. You may be able to cast it to A to access either method (depending on A's visibility), but that's unlikely to happen by mistake.

like image 31
shmosel Avatar answered Oct 12 '22 22:10

shmosel