Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why public class can't extend private class?

Tags:

kotlin

I have a following class hierarchy:

interface Repository

// This class contains some common stuff for LocalRepository and RemoteRepository. I'm never going to use this class outside this file, so I make it private
private abstract  class BasicRepositoryImpl

// these classes are designed to be instantiated in other files    
class LocalRepository : BasicRepositoryImpl(), Repository // error

class RemoteRepository : BasicRepositoryImpl(), Repository // error

But I get the following error:

Subclass effective visibility 'public' should be the same or less permissive than its superclass effective visibility 'private'

I don't want to use BasicRepositoryImpl anywhere else, so it's declared private, and I want to use LocalRepository and RemoteRepository in other files like this:

class Presenter(val repo: Repository)

val p = Presenter(LocalRepository())

But that error prevents me to create such a hierarchy. Why? What's wrong with it?

like image 734
netimen Avatar asked Feb 17 '16 15:02

netimen


People also ask

Can a public class extend a private class?

The answer is you can't extend the Parent class if it has a private default constructor. You have to make the constructor available to the subclass. In this case you need to have a default constructor that have a protected or public or default access modifier.

Can we extend the private class in Java?

No, we cannot override private or static methods in Java. Private methods in Java are not visible to any other class which limits their scope to the class in which they are declared.

Can we extend a class which has private constructor?

When you have a class with only private constructors, you can also change the class to final because it can't be extended at all.

Can a private class have public constructor?

Private constructors in Java are accessed only from within the class. You cannot access a private constructor from any other class. If the object is yet not initialised, then you can write a public function to call the private instructor.


1 Answers

The class and its ancestors must all be accessible from the using class. Otherwise it would be an violation when loading the ancestor class, not just calling its methods or using its functionality. Kotlin is very clean and clear about this in all cases where accessibility is present.

Opening it up a little would allow things that could cause real JVM access violations later, like an inline function in the public class, inlined into another class, calling the private non accessible something of the ancestor. There are many holes you aren't considering if you feel it is ok to do a mixed model of accessibility like this. The matrix of considerations is larger than only the desire to hide some classes from instantiation.

With the class being abstract, it cannot be used directly other than as an ancestor, so you have some protection already. If you want to block use as an ancestor outside of your module, make its constructor private or internal and that will solve that problem:

abstract class BasicRepositoryImpl private constructor() { ... }

Now you have protected direct instantiation (abstract) or use as a base class (by using abstract and private constructors) so the last things to do is give it a good name like AbstractBaseRepository and people will by convention leave it alone.

If you want to discuss "why" this is the design decision, or technical limitation, or protective rule ... then try the discussion forums, a feature or language change suggestion in YouTrack. But beware things are not as simple as they first appear to be. These rules are there for reasons (even if other languages dangerously allow).

like image 87
2 revs Avatar answered Nov 04 '22 04:11

2 revs