简体   繁体   中英

Get instance of subclass with superclass static method

I have a superclass that I would like to forward a static method called getInstance() to all subclasses.

When creating an instance of a subclass, I then register the instance in the superclass (perhaps using a hashtable, where the key is based on getClass() ). Then, I wish to use the aforementioned static method ( getInstance ) where the superclass method will return the instance of the correct type.

For example, I have a superclass A, and a subclass B extends A. I want to write a static method A.getInstance() ; when called from B ( B.getInstance() ), I would like it to return the instance of B that I stored earlier.

Its kinda hard to explain, but I am going to be using this superclass a lot, and I would rather not code a getInstance method into every single subclass.

How would I go about doing something like this?

edit: I just realized that my question may be misconstrued as creating a NEW instance of the object. I have already created the instance, and i wish to get the existing instance of the class

As many others have noted in the comments, what you are trying to do is not possible with static methods. Also, you should try to avoid static methods whenever possible because they can result in a testing and maintanance nightmare (*).

You named your method "getInstance", so I guess what you want to do is a mix of Factory- and Singleton patterns. Here is some information to get you started about these patterns:

Singleton: http://en.wikipedia.org/wiki/Singleton_pattern
Factory Method: http://en.wikipedia.org/wiki/Factory_method_pattern
Abstract Factory: http://en.wikipedia.org/wiki/Abstract_factory

Both should not be coded by hand in these days (*) - Have a look at a good "Dependency Injection" (DI) container like Google Guice or Spring. I am not 100% sure what exactly you want to achieve, but it looks like a DI container will do it for you.

Edit: This is a response to an edit of the question. You want to receive a cached instance of the sub classes. In this case, I would still advise against static methods. You could create a singleton instance of a "BCache" class (using a DI container or programming it by hand), and then use this cache object to look up your registered objects. Using Guice as a DI container, it could look like this (warning, untested):

@Singleton
public class BCache {
    private Map<Class<? extends B>, B> cache = ...;

    public <T> T getInstance(Class<? extends T> type) {
        return (T) cache.get(type);
    }
}

I still think it would be possible to get rid of the cache class completely using a DI container, though. Again, this is untested code, using Guice, but it could look like this:

@Singleton
public class A extends B {
    public A() {
        //I am not sure if you need to register in this case, because your
        //DI container keeps track of the singleton instances.
        super.register(this);
    }
}

public class SomeClassUsingA {
    @Inject private A a;
}

(*) Note that "all generalizations are wrong", that is, in some projects it might make sense, but in most it will not.

You can't do exactly what you want with the static methods, in good OOP way. You can can do something with the reflection or bunch of if .. else if .

You however, should use some well defined design patterns like Abstract fectory or Factory method . This is the way you should go, like someone said "Don't invent warm water".

You can always assign a subClass instance to a superClass reference. Therefore your superClass's static methods can set or get a subClass instance. But make sure to cast the returned instance before using.

public class A {
    private static A a;

    /**
     * @param a the a to set
     */
    public static void setA(A a) {
        A.a = a;
    }

    /**
     * @return the a
     */
    public static A getA() {
        return a;
    }


public class B extends A {
    private int index = 0;

    /**
     * @param index the index to set
     */
    public void setIndex(int index) {
        this.index = index;
    }

    /**
     * @return the index
     */
    public int getIndex() {
        return index;
    }

Usage:

public static void main(String[] args) throws Exception {
        B b = new B();
        A.setA(b);

    B c = (B) A.getA();
    System.out.println(c.getIndex());
}

Change form getInstance() to getInstance(String class) in the superclass:

public static A getInstance(String class){
if(class.equals("A")){
RegisterObject(...);//User defined method
return new A(...);
}
else if(class.equals("B")){
RegisterObject(...);//User defined method
return  new B(...);
}
else if(class.equals("C")){
RegisterObject(...);//User defined method
return  new C(...);
}
//... and so on

}

Static methods are cannot know which class is used to invoke them. If for example you have class A and B that extends A and static getInstance() implemented in A there is no difference whether you invoke getInstance() using A or B . Moreover attempt to call B.getIntance() will produce compilation warning (at least in Eclipse).

However you can pass the class as a parameter of getInstance() :

public class A {
    public static <T extends A> T getInstance(Class<T> clazz) {
        return clazz.newInstance(); // I do not catch exceptions here: do it yourself
    }
}

public class B extends A {
}

...............
B b = A.getInstance(B.class);

You can do like this way,

 class A{
     public static A getInstance(){
     return new A();
   }

  @Override
  public String toString() {
   return "inside A";
   }
 }

 class B extends A{
public static A getInstance(){
  return new B();
 }

   @Override
   public String toString() {
      return "inside B";
   }
 }

inside main :

   public static void main(String[] args) {
  A a1 = A.getInstance();
  A a2 = B.getInstance();
      System.out.println(a1.toString());
  System.out.println(a2.toString());
   }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM