2

Is there some object oriented thing that you can call some methods from certain classes, but not all of them? Is there something like that which is similiar to protected?

Say you have a method void foo() and you want it to be available to the programmer in a few types of classes (perhaps something like using Type variables (to specify: T type). Now, perhaps is there some way, without inheriting the class with foo() in it, or making an interface, to specify which classes or types of classes have access to that method?

I would guess this could be like multiple-inheritance and polymorphism? But I still want only the class and certain classes to access the method without changing the visibility of the method. I want the visibility to be class-specific.

Here is an example:

class A sees foo() as private, but only that class sees it as private.
class B sees foo() as public/protected, but only that class sees it as public.

The method type would be default.

I guess what is easier to ask and answer to is: "Is there class-specific visibility?"

AMDG
  • 1,118
  • 1
  • 13
  • 29

4 Answers4

4

There is something like you are asking for in C++, it is called friend classes. Nevertheless, that concept is not supported by Java:

'Friends' equivalent for Java?

A second option is to use code reflection to access a class private members but it isn't such a clean solution and only works for protected elements:

public class C1 {

    public C1()
    {
        x = "Hello Word!";
    }

    protected String x;
}

At a different class's method:

String val = (String)obj.getClass().getDeclaredField("x").get(obj);
System.out.println("val: " + val);

EDIT: After making a little bit of research I found it is possible even to access private members:

Field field = obj.getClass().getDeclaredField("x");
field.setAccessible(true);
String val = (String)field.get(obj);
field.setAccessible(false);
Community
  • 1
  • 1
  • 2
    Frankly I'm glad Java doesn't have friend classes. It's a mess. – Mikkel Løkke May 30 '14 at 12:49
  • 1
    If only my DynamicWindow and Debugger were `friends`... then I could actually get this GraphicsOptimizedThreadedOeuvre working right! – AMDG May 30 '14 at 12:51
  • Or perhaps is there a jvm arg that you can specify for the accessors of the method perhaps? Then again, one could just make an unofficial Java version that includes friends or perhaps maybe... JNI? Perhaps a .cpp file that _can_ have friends could make it possible. But that seems like a big project just to set visibility... – AMDG May 30 '14 at 13:08
  • the edit was useful, thanks, but I already have that in my debugger for _debugging purposes only_. Also, its breakin' the law so I'd rather not use reflection; its slow and really should only use it when necessary and proper, kind of like the constitution and the government... – AMDG May 30 '14 at 13:11
  • Hmm, well... though slow and big, I guess you could define your own Java source file that defines friends for you I _guess_... – AMDG May 30 '14 at 13:40
  • I'm not quite sure how this answers the question (or why it was accepted). This is "how you can get round access control" - it's not "how can you grant access only to a specific set of classes" which was what was being asked... – Jon Skeet May 30 '14 at 14:11
  • 1
    @JonSkeet My answer as yours states that it is not possible to grant access as the OP asks but I tried to give him an alternative way to get what he needs. I could had finished it saying "not possible" but here we are to share our points or view concerning problems solutions. I feel sorry you don't consider it worth of be accepted. – Pablo Francisco Pérez Hidalgo May 30 '14 at 14:25
  • 1
    @PabloFranciscoPérezHidalgo: It's more that it spends most of its space giving the reflection part, which doesn't seem relevant. Without wishing to claim that my answer should have been accepted instead, I would say my answer at least gives alternatives for restricting visibility to *some* classes - it turns out it doesn't meet the OP's needs, but I personally think it's closer to giving an option than the reflection part. Not a massive problem though... – Jon Skeet May 30 '14 at 14:27
1

Access Levels

Modifier    Class   Package Subclass  World
public       Y        Y       Y        Y
protected    Y        Y       Y        N
no modifier  Y        Y       N        N
private      Y        N       N        N

thats your lot, there are not any other access modifiers.

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
  • Minor point, but I'd remove the markdown from `default`, just to make it clear the it's not used explicitly to modify access like the other three – darrengorman May 30 '14 at 12:48
  • `default`is commonly reffered to as `package-private` in the Java documentation. http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html – Mikkel Løkke May 30 '14 at 12:52
  • this is probably a question within a question but, are default variables package-private to only that package or can you access a sub-package default Object from a super-package? – AMDG May 30 '14 at 13:48
1

No, there's nothing like that in Java.

The closest you've got is putting classes within the same package, at which point they have access to any members which don't specify any access modifier. You can't specify particular classes though.

Another option which is appropriate in some cases is to use nested classes:

class Outer {
    private static class Inner {
    }
}

Here Outer and Inner have access to each other's private members.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Hmm that surely is a possibility but with friends... that is not appropriate for the project I'm working on. These classes are _entirely_ independant of eachother and the classes that utilize this Oeuvre should not know _anything_ about the objects except to make instances of them... unless I make some class that stores Objects, but that would be redundant and inefficient... why make copies of a variable? Its has already been stored/initialized once. – AMDG May 30 '14 at 13:45
  • @LinkTheProgrammer: I'm not quite sure I follow your example (you haven't really given us enough context) but basically, the answer is "no". – Jon Skeet May 30 '14 at 14:10
0

With a little sleight of hand you can make one class seem to be two different classes:

// An interface.
interface A {
    public void a ();
}

// Another interface.
interface B {
    public void b ();
}

// Deliberately NOT stating we implement either A or B but actually we implement both.
class C {
    public void a () {

    }
    public void b () {

    }
}

// Pick either implementation from C and tell the world about it.
class D extends C implements A {
    // Do nothing - already done by C.
}

class E extends C implements B {
    // Do nothing - already done by C.
}

public void test() {
    A d = new D();
    B e = new E();
}

Here D and E are actually identically functioned objects because they are both actually Cs. However, as they are created they are made to seem to be A or B which are two different interfaces.

Unfortunately we cannot hide the fact that they both extend C but a little further sleight of hand and we can do that too with a Factory.

// Hide the guts of it all in a factory.
static class Factory {
    // Make sure you MUST use the factory methods.
    private Factory () {

    }

    // Construct an A.
    public static A newA () {
        return new D();
    }

    // Construct a B.
    public static B newB () {
        return new E();
    }
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • umm, no interfaces... this Oeuvre should do the work _for_ the programmer, not _make more work for the programmer_. – AMDG May 30 '14 at 13:42