5

So, we have

public abstract class A{
    protected abstract String f();
}

public class B extends A{
     protected String f(){...}
}

public class C extends A{
    protected String f(){
         A b = (A) Class.forName("B", true, getClass().getClassLoader()).newInstance();
         return b.f();
}

This doesn't allow me to access b.f(), saying that B.f() is in the protected scope, however f was protected by A, and since C extends A, it should also get access to f().

f.khantsis
  • 3,256
  • 5
  • 50
  • 67
  • Why not create new instance like : A b = (A) new B(); ? – Dmitry Jul 07 '15 at 08:58
  • B is only available at runtime. If you really want to know, B is `com.android.okhttp.HttpsHandler`, and A is `URLStreamHandler` – f.khantsis Jul 07 '15 at 09:00
  • You can solve your case via reflection, but it would be more helpful if you posted your *original* problem. Which method of `HttpsHandler` are you trying to call and why do you need it. See the [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Consider opening a new question with your original problem. – Tagir Valeev Jul 07 '15 at 09:08
  • don't you have a feeling you're doing something wrong? if so, why are you trying to make it worse? – AdamSkywalker Jul 07 '15 at 09:10
  • Because that's the only way. The class is only available at runtime, and this reflection is how it is actually done in `URL`, which is in the same package as `UrlStreamHandler`. Oh well, I guess I can't use this functionality. My original problem is to make all HttpsConnections use my custom certificate. I wanted to do it by creating my own URLStreamHandler, which would delegate to default stream handlers to open connections, just do `setSSLSocketFactory` if the protocol is https. My custom `URLStreamHandler` would then be sent to URL.setURLStreamHandlerFactory. – f.khantsis Jul 07 '15 at 09:12
  • @doom777 I hope you go and ask how to resolve this problem, not just move your class to com.android.okhttp package – AdamSkywalker Jul 07 '15 at 09:34
  • I just abandoned this path. I will simply provide my `URLStreamHandler` every time I want a secure URL, and to get a delegate URL connection inside the stream handler, I just build a new URL with the same spec with default stream handler, and take its connection. Less pretty, but it works and is best I can do. – f.khantsis Jul 07 '15 at 09:42

2 Answers2

3

The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

If you want to access the B.f(), you should have the C class defined in the same package as B.

Alex Objelean
  • 3,893
  • 2
  • 27
  • 36
  • but this level of accessibility can be achieved by using no modifiers(known as "package private"). If a subclass that accesses protected methods must by in the same package does it means that package private and protected modifiers does the same? I think subclass that accesses protected methods can be in any package. Correct me if I'm not right. – Dmitry Jul 07 '15 at 09:26
  • You are correct. The answer try to solve the problem as it is stated in the question. – Alex Objelean Jul 07 '15 at 09:28
  • 1
    Now i see. But variable b is of type A, and instance of B() is casted to A. This moment is interesting why access is illegal – Dmitry Jul 07 '15 at 09:30
  • 2
    That is because the C class is defined in a different package and you cannot access other than public fields on an instance. – Alex Objelean Jul 07 '15 at 09:39
0

No because the compiler does not know whether b is an instance of B, C, or other external classes.

Suppose there is a class D such that D extends A in another package. If b is an instance of D (the compiler does not know) b.f() should be forbidden if the access is protected (can't be accessed by classes in other packages).

tonychow0929
  • 458
  • 4
  • 10
  • as long as b is an A, and A has `f`, what does it matter? – f.khantsis Jul 07 '15 at 09:06
  • @doom777 suppose now `b` is a `D`, where `D extends A` and is defined in another package with a `protected` `f()` method. Considering `D`, `A` is in "another package", so `A` cannot access `protected` methods in `D`. However the compile doesn't know whether `b` is an `B`, `C` or `D`, so `b.f()` must be forbidden (in case `b` is an instance of `D`). – tonychow0929 Jul 07 '15 at 09:14
  • I would think that because `f` was defined originally in `A`, it should always remain as a child of `A` or freer, and available to all `A`s and its subclasses – f.khantsis Jul 07 '15 at 09:18
  • @doom777 The fact that `D` is not a subclass of `C` makes `f()` in `D` unavailable to `C`... =) – tonychow0929 Jul 07 '15 at 09:23
  • I'd say it shouldn't because it was originally defined in `A`, so it protected in C really means protected of `A` and it should be available to all subclasses of `A`. – f.khantsis Jul 07 '15 at 09:25
  • @doom777 `protected` in `D` is different from `protected` in `A`. In fact a subclass can always redefine the access modifier (as long as the access modifier isn't more restrictive). In this case I would consider the access modifiers to be "independent". – tonychow0929 Jul 07 '15 at 09:29