19

Let's assume I have classes A, B, and C where class C has readable and writable properties:

public class C {
    private int i = 0;

    // Writable.
    public void increment() { i++; }

    // Readable.
    public int getScore() { return i; }
}

Is it possible to only let A use the increment() method and only let B use the getScore() method?

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
sdasdadas
  • 23,917
  • 20
  • 63
  • 148

6 Answers6

29

No, it is not possible to assign per-class access.

Consider separating your class into separate interfaces so that each class only gets an object with the interface it needs. For example:

interface Incrementable { public void increment(); }
interface HasScore { public int getScore(); }
class C implements Incrementable, HasScore { /* ... */ }

class A {
  public A(Incrementable incr) { /* ... */ }
}

class B {
  public B(HasScore hs) { /* ... */ }
}

Of course, there are security implications but this should get you thinking in the right direction.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • Thanks - waiting on the timer now. – sdasdadas Feb 05 '13 at 22:37
  • Isn't there a way if he made abstract class and then implement those methods – Smit Feb 05 '13 at 22:39
  • @Smit That's essentially the same thing - the abstract class would allow you to implement some common details, though. – sdasdadas Feb 05 '13 at 22:43
  • @sdasdadas Just want to make sure. So abstract class can be used to solve the problem. I am asking this because of you reference `That's essentially the same thing ` to question or to answer. – Smit Feb 05 '13 at 22:48
  • @Smit You can only extend one Abstract class, where you can implement (afaik) any number of interfaces. You'd want to use interfaces in the context of the question I believe. – crush Jun 23 '15 at 22:32
6

Yes it is, but you have to go through some gyrations.

public interface Incrementable {
    public void increment();
}

public interface Readable {
    public int getScore();
}

public class C implements Incrementable, Readable
{
    ...
}

Now when you define the method in A that receives a reference to a B instance, define that method to take an Incrementable instead. For B, define it to take a Readable.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
3

Java has 4 scopes: private, protected, public and "package". Something that is public can be accessed from anywhere. protected only from subclasses. private is only that class. "package" scope is not named, but if you omit any of the other three, it is assumed package scope. This is only accessible by other classes in the same package.

HTH.

Steve H.
  • 6,912
  • 2
  • 30
  • 49
  • 4
    `protected` does not mean that a field/method/class can be accessed from subclasses only. Classes from the same package are allowed to use what's `protected` as well. – toniedzwiedz Feb 05 '13 at 22:36
  • But you're absolutely correct about "package". If the class needing access is in the same package it will have access to the method but others won't. – Rick Mangi Feb 06 '13 at 00:44
2

No it is not possible to do that.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
2

Not that you'd want to, but you could go up the stack trace (create an exception) and check the class that's calling your increment method.

Steve Kuo
  • 61,876
  • 75
  • 195
  • 257
1

Although the straight answer is no, another workaround(an ugly one) could be to create two interfaces extending a third(or you could just take an Object as parameter): Reader and Writer, to pass the calling class as a parameter to each function:

public interface Caller;
public interface Reader extends Caller;
public interface Writer extends Caller;


public void increment(Caller c) { 
     if (c instanceof Writer) {
         i++;
     } 
}
Vlad Topala
  • 896
  • 1
  • 8
  • 34