How do I extend a Singleton class?
I get error :
Implicit super constructor Demo() is not visible. Must explicitly invoke another constructor.
package demo;
public class Demo {
private static Demo instance;
private Demo(){}
public static Demo getInstance(){
if(instance ==null){
instance=new Demo();
}
return instance;
}
}
It's not strictly about it being a singleton, but by default when you extend a class, Java will invoke the parent's no-arg constructor when constructing the subclass. Often to stop people creating random instances of the singleton class, the singleton's no-arg constructor will be made private, e.g.
private Demo() {...}
If your Demo class doesn't have a no-arg constructor that's visible to the subclass, you need to tell Java which superclass constructor to call. E.g. if you have
protected Demo(String param) {...}
then you might do
protected SubDemo() {
super("something");
...
}
and/or
SubDemo(String param) {...}
{
super(param);
}
Note that if your Demo class has no non-private constructors, you won't be able to usefully extend it, and (if possible) you would need to change the protection level on at least one constructor in the Demo class to something that is accessible to your subclass, e.g. protected
Related
I'm a begginer programmer for Android and I found some code over the internet and I couldn't get what this "Class not meant to be instantiated" means?! Also what's the use of it. I would be very happy if somebody could help here.
public class Settings
{
//some code
private Settings() {} // Class not meant to be instantiated
//some code
}
The constructor is private so only the class itself can create instances. There are several reasons for doing this. A couple off the top of my head...
The class is a "utility" class that only contains static methods and so instantiating it would make no sense. As the class is commented "Class not meant to be instantiated" I guess this is the most likely reason.
The class itself controls its own lifecycle and provides methods for creating instances. For example if the class is a lazy singleton it might provide a method that creates an instance when first called and return this instance on subsequent calls.
It is a private constructor. This means that outside classes cannot create new instances using the default constructor.
A little more info
All Objects in Java have a default constructor:
public MyObject() {}
That is how you can have this class:
public class MyObject{}
and still be able to call:
MyObject mObj = new MyObject();
Private Constructors
Sometimes a developer may not want this default constructor to be visible. Adding any other constructor will nullify this constructor. This can either be a declared constructor with empty parameters (with any of the visibility modifiers) or it can be a different constructor all together.
In the case above, it is likely that one of the following models is followed:
The Settings object is instantiated within the Settings class, and is where all the code is run (a common model for Java - where such a class would also contain a static main(String[] args) method).
The Settings object has other, public constructors.
The Settings object is a Singleton, whereby one static instance of the Settings Object is provided to Objects through an accessor method. For example:
public class MyObject {
private static MyObject instance;
private MyObject(){}//overrides the default constructor
public static MyObject sharedMyObject() {
if (instance == null)
instance = new MyObject();//calls the private constructor
return instance;
}
}
This inner construct
private Settings() {}
is a constructor for Settings instances. Since it is private, nobody can access it (outside of the class itself) and therefore no instances can be created.
The constructor is private so its not meant to be called by anything outside of the class
It's not a nested class, it's a constructor. A private constructor means that you can't construct instances of this class from outside, like this:
Settings s = new Settings(); //Compilation error! :(
Now, if a class can't be instantiated, what could it be for? The most likely reason for this is that the class would return instances of itself from a static method, probably as a singleton. The settings are normally global to the program, so a singleton pattern really fits here. So there would be a static method that goes kind of like this
static private TheOnlySettings = null;
static public getSettings()
{
if(TheOnlySettings == null)
TheOnlySettings = new Settings(); //Legal, since it's inside the Settings class
return TheOnlySettings;
}
See if that's indeed the case.
As other have mentioned, a class having private constructors cannot be instantiated from outside the class. A static method can be used in this case.
class Demo
{
private Demo()
{
}
static void createObjects()
{
Demo o = new Demo();
}
}
class Test
{
public static void main (String ...ar)
{
Demo.createObjects();
}
}
We can have private constructor . Below program depicts the use of private constructor with a static function
class PrivateConstructor {
private:
PrivateConstructor(){
cout << "constructor called" << endl;
}
public:
static void display() {
PrivateConstructor();
}
};
int main() {
PrivateConstructor::display();
}
What would happen if we change the constructor of the singleton from private to protected? How we can prevent it breaking in that case?
Singleton:
public class SingletonObject
{
private static SingletonObject ref;
private SingletonObject () //private constructor
{
System.setSecurityManager(new SecurityManager());
}
public static synchronized SingletonObject getSingletonObject()
{
if (ref == null)
ref = new SingletonObject();
return ref;
}
public Object clone() throws CloneNotSupportedException
{
throw new CloneNotSupportedException ();
}
}
For breaking the singleton the following url contains the required info cracking singleton with other ways.
From Joshua Bloch's Effective Java on Singletons Properties:
The private constructor is called only once, to initialize the public
static final field (...). The lack of public or protected
constructors guarantees a “monoinstance” universe: Exactly one (...)
instance will exist once the Singleton class is initialized—no more, no
less. Nothing that a client does can change this.
So, if you make your Singleton Constructor protected you're exposing your Constructor to let any class in the same package to make instances an instance of SingletonObject. If that happens, your Singleton Pattern is broken.
Relaxing the access modifiers of the constructor on any way -making it protected, public or default- is an open gate to instance generation, and that's not desired in a Singleton implementation.
Simple: Changing the constructor access modifier from private to protected allows any class in the same package to instantiate SingletonObject. We can easily create a class "in the same package" by specifying the corresponding package statement.
Edit: The answer of Carlos made me realize an additional problem that results from making the constructor protected as opposed to public: A subclass of the singleton class can be created (in another package), which can be freely instantiated and have its instance methods called; the singleton class itself no longer has full control over where and how instances (or 1 instance) are created.
In my coding, I use Singleton class with Singleton Design Pattern. Question is why its sub class does not allowed to use default constructor?
I get compile time error :
Implicit super constructor Singleton() is not visible. Must explicitly invoke another constructor
Singleton.java
public class Singleton {
private static Singleton singleton;
private Singleton() {
System.out.println("I am user class");
}
public static Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
SubClass.java
public class SubClass extends Singleton {
public SubClass(){
System.out.println("I am sub class");
}
}
When you create an instance of SubClass then it automatically invokes the constructor of its SuperClass to initialize its fields, and that further invokes all the superclass constructors in the inheritance hierarchy
Now since your SuperClass constructor is private, so it cannot invoke that. So, you are getting that exception..
But it doesn't make sense to subclass a singleton class, because in that case, your class will no longer be singleton.
You should re-think about your design and what you are trying to do. And change your design accordingly.
SingleTon class are not supposed to be inherited so below ensures that
private Singleton() {
Below code
public SubClass(){
System.out.println("I am sub class");
}
Is same as :
public SubClass(){
super(); //Error here as super class constructor is private
System.out.println("I am sub class");
}
Because your Singleton class no-arg constructor is private. When you instantiate sub-class it tries to instantiate super class also. But your super class has private constructor. It fails.
private Singleton() {
System.out.println("I am user class");
}
It doesn't make sense to subclass Singleton class. You may need to re-think about your design.
First of all, subclassing a singleton class is breaking the basics of Singleton Pattern.
Secondly, due to the chain of calling the constructors through the inheritance tree, you get that exception since the constructor of the parent class is private.
You will probably add a public constructor with some parameters to make the child inherit from its parent. Then you will have maybe many instances of SubClass. Any Subclass instance IS-A Singleton instance, too. And this is against the purposes of Singleton pattern. That's why you should avoid subclassing a singleton class.
The following is my ProtectedConstructor.java source code:
package protectCon;
public class ProtectedConstructor{
public int nothing;
ProtectedConstructor(){
nothing = 0;
}
}
And following is the UsingProtectedCon.java source:
package other;
import protectcon.ProtectedConstructor;
public class UsingProtectedCon extends ProtectedConstructor{ //**Line 4**
public static void main(String... a) {
}
}
When I compile UsingProtectedCon.java, I get error at Line 4 shown above. It says that ProtectedConstructor() is not public ; so cannot be accessed outside package.
However, since my class is public, shouldn't I be able to extend it outside package. I am anyway not creating any instance of it.
Now, if I make the constructor of ProtectedConstructor class as public or protected then the code compiles fine with no error.
So then why is it necessary even for the constructor to be public or protected, and not just have default access?
If you want to extends a class outside its package it must have a constructor that is public or protected because in Java every constructor must call a constructor from its superclass.
Because of this there is an implied super() call in every constructor which does not have this() or an explicit call to super() as its first statement. And if you don't specify a constructor at all Java will add a default parameterless constructor, so in effect your code looks like this:
public class UsingProtectedCon extends ProtectedConstructor {
public UsingProtectedCon() {
super();
}
public static void main(String... a) {
}
}
So in other words your code is failing to compile because the call to super() in the default constructor cannot be resolved.
constructor is a member of class like field and method so access modifier applies to it in the same manner it apples to all the member of class
when you extend the class A in B , A's its default constructor will get called from B's constructor implicitly (if you don't call any of the overloaded constructor)
in your class ProtectedConstructor is defined with Package-Private access
This means that outside the package its not seen even by the classes that extend from your ProtectedConstructor class
Define your constructor with 'protected' access modifier instead and you'll be done:
package protectCon;
public class ProtectedConstructor{
public int nothing;
protected ProtectedConstructor(){
nothing = 0;
}
}
Your constructor is not public. Default scope is package-private.
JLS 6.6.7 answers your question. A subclass only access a protected members of its parent class, if it involves implementation of its parent. Therefore , you can not instantiate a parent object in a child class, if parent constructor is protected and it is in different package.Since the default constructor of the subclass would try to call parent class constructor ,you got this error.
See this SO Post for details
to avoid all confusion do it like this.
package protectCon;
public class ProtectedConstructor{
public int nothing;
public ProtectedConstructor(){
nothing = 0;
}
}
package other;
import protectCon.ProtectedConstructor;
public class UsingProtectedCon extends ProtectedConstructor{ //**Line 4**
public UsingProtectedCon(){
super();
}
public static void main(String... a){
}
}
You can have constructors which are public, protected (for internal used) and even private.
A simple example is String which has public constructors for general use and package-local constructors for internal use.
The ObjectOutputStream class has a public constructor which takes an OutputStream and a protected constructor which can only be used by a sub-class.
BTW: if you have an abstract class, does it make sense to make the constructor public as if often the case. ;) hint: it is the same as protected.
If child will have constructor which is private in parent,we can make child's instance with that constructor and cast it to parent's type.
So to prevent this java compiler is not allowing constructor to have constructor which is private in parent.
In Java, I can't create instances of abstract classes. So why doesn't eclipse scream about the following code?
public abstract class FooType {
private final int myvar;
public FooType() {
myvar = 1;
}
}
The code is fine, the final variable is initialized in the constructor of FooType.
You cannot instantiate FooType because of it being abstract. But if you create a non abstract subclass of FooType, the constructor will be called.
If you do not have an explicit call to super(...) in a constructor, the Java Compiler will add it automatically. Therefore it is ensured that a constructor of every class in the inheritance chain is called.
You can have constructors, methods, properties, everything in abstract classes that you can have in non-abstract classes as well. You just can't instantiate the class. So there is nothing wrong with this code.
In a deriving class you can call the constructor and set the final property:
public class Foo extends FooType
{
public Foo()
{
super(); // <-- Call constructor of FooType
}
}
if you don't specify a call to super(), it will be inserted anyway by the compiler.
You can create concrete sub-classes of FooType and they will all have a final field called myvar.
BTW: A public constructor in an abstract class is the same as a protected one as it can only be called from a sub-class.
What is your doubt?
Ok. See, an abstract class can have a constructor. It's always there-implicit or explicit. In fact when you create an object of a subclass of an abstract class, the first thing that the constructor of the subclass does is call the constructor of its abstract superclass by using super(). It is just understood, that's why you don't have to write super() explicitly unless you use parameterized constructors. Every class even if it is abstract, has an implicit constructor which you cannot see. It is called unless you create some constructor of your own. so long you created abstract classes without creating any custom constructor in it, so you didn't know about the existence of the implicit constructor.
You definitely can declare final variable in abstract class as long as you assign value to it either in the constructor or in declaration. The example that guy gave makes no sense.
No you can't declare final variables inside an Abstract class.
Check Below example.
public abstract class AbstractEx {
final int x=10;
public abstract void AbstractEx();
}
public class newClass extends AbstractEx{
public void AbstractEx(){
System.out.println("abc");
}
}
public class declareClass{
public static void main(String[] args) {
AbstractEx obj = new newClass ();
obj.AbstractEx();
// System.out.println(x);
}
}
This code runs correct and produce output as
abc
But if we remove comment symbol of
System.out.println(x);
it will produce error.