Reputation: 3731
Here's an example:
class A
{
List l = new List ();
list.insert("x");
}
class List
{
...
public void insert ()
{
/*insertion occurs*/
}
...
}
Is it possible at all to keep the insert() method public, but limit access only to class A so that no other class can access it, only when called from A?
Upvotes: 10
Views: 15717
Reputation: 261
Yes, you can pass calling object as an argument and put a check in insert() method before actual code.
public void insert(Object obj){
if(obj instanceof A){
//your code block
}
}
Please note that this will allow all the classes that extends A as well to call insert. If you want to restrict only for class A, add additional check.
public void insert(Object obj){
if((obj instanceof A) && obj.getClass().getSimpleName().equals("A")){
//your code block
}
}
we can also achieve second case with only condition "obj.getClass().getSimpleName().equals("A")" as well.
Upvotes: 2
Reputation: 726479
If the method is public, everyone can access it. The trick to access control like yours is to expose a set of public operations through an interface, add auxiliary operations to a private class implementing the interface, and make your users program to the interface, not to a class.
Here is an example:
public interface MyList {
Object elementAt(int i);
}
public class A {
private static class MyListImpl implements MyList {
public Object elementAt(int i) {
...
}
public void insert(Object element) {
...
}
}
private final MyListImpl list = new MyListImpl();
public MyList getList() { return list; }
public void insert(Object o) { list.insert(o); }
}
Usage scenario:
A a = new A();
a.insert(123);
a.insert("quick brown fox");
MyList lst = a.getList();
System.out.println(lst.elementAt(0));
System.out.println(lst.elementAt(1));
Upvotes: 6
Reputation: 395
I would pass the object that is calling the method as an argument, i.e.
list.insert("x", this);
And then check if the passed Object is an Instance of Class A
public void insert (String x, Object o)
{
if(o instanceof ClassA){
/*insertion occurs*/
}
}
Upvotes: 7
Reputation: 2301
package problems;
public class Problem1 {
public static void main(String[] args) {
B b = new B();
b.methodInB();
C c = new C();
c.methodNotInB();
}
}
class A {
public void onlyB() {
StackTraceElement[] stackTraceElements = Thread.currentThread()
.getStackTrace();
if (!problems.B.class.getCanonicalName().equals(
stackTraceElements[stackTraceElements.length - 2]
.getClassName())) {
System.err.println("You are not authorized to call me!!");
return;
}
System.out.println("You are authorized to call me!!");
}
}
class B {
public void methodInB() {
A a = new A();
a.onlyB();
}
}
class C {
public void methodNotInB() {
A a = new A();
a.onlyB();
}
}
Upvotes: 1
Reputation: 11572
If all the "inner classes" stuff in the previous answers confuses you, there is another way that may be more intuitive (assuming you've learned about the extends
keyword and inheritance). You can simply make the insert()
method protected
instead of public
and make class A
extend List
. For example:
public class List {
...
protected void insert() {
//insertion occurs
}
...
}
public class A extends List {
...
}
As long as no other classes extend List, only objects of types A
and List
will ever be able to use the insert()
method.
Upvotes: 1
Reputation: 1546
Put it as inner class in A or you can do another thing ... Let insert takes one parameter with type of Object and in the beginning of it check if the parameter's type is A .... and when you call it send the calling object... maby its not a good idea but it will do what you want
Upvotes: 0
Reputation: 120138
The best you can do using access modifiers is to make the method package private (remove the public
keyword) and keep only those two classes in the same package.
Upvotes: 1