I'm trying to write a factory method in an abstract class in Java (so I want it to return a new instance of the extending class, rather than the super-class).
In PHP I'd do this using the self keyword:
abstract class Superclass {
public static function factory($arg) {
return new self($arg);
}
private function __construct($arg) {}
abstract public function doSomething() {}
}
Does Java have a keyword like self I can use for this?
No; in Java, static methods are not inherited in the same way as non-static methods are. A subclass will have the static methods of its superclass, but when they execute, they will execute in context of the superclass - so there is no keyword that can be used in static methods to find out what class the method was invoked through.
Edit: A more precise formulation is that static methods are not inherited at all; however, the language allows us to use Subclass.foo() to call the static method Superclass.foo().
Based on what you seem to want to achieve, you might want to implement the Abstract Factory pattern. It goes approximately like this:
public abstract class Superclass {}
public class SubclassA extends Superclass {}
public class SubclassB extends Superclass {}
public abstract class AbstractFactory {
public abstract Superclass Create();
}
public class FactoryA extends AbstractFactory {
public Superclass Create() {
return new SubclassA();
}
}
public class FactoryB extends AbstractFactory {
public Superclass Create() {
return new SubclassB();
}
}
Now, you can e.g. create a method that takes an AbstractFactory (which, in reality, will be either a FactoryA or a FactoryB). Calling Create() on this object will produce either a SubclassA or a SubclassB.
Edit: Fixed compilation error (forgot to make the factories extend AbstractFactory).
If you absolutely have to you can use this code form a static context:
Class cls = new Object() { }.getClass().getEnclosingClass();
Object instance = cls.newInstance();
Your class need to have a nullary constructor.
You need some hacks to achieve this. One way I can think of to obtain this is:
public static <T extends SuperClass> T factory(Class<T> clazz) {
return clazz.newInstance();
}
I don't think it is possible in Java to find out the name of the "current" subclass. And especially some dynamic object generation won't be possible.
So you'll need to define that static function in every subclass instead.
Related
I have a generic class that looks like:
public abstract class Foo<T extends Foo<T>> {...
and another class that looks like:
public abstract class Fum<T extends Fum<T,U>, U extends Foo<U>> {...
and finally some subclasses that look like:
public class SubFoo extends Foo<SubFoo> {...
public class SubFum extends Fum<SubFum,SubFoo> {...
In the abstract classes, there are abstract methods declared public abstract T create(); (with overloaded versions) which are responsible for instantiating subclass objects used in the superclass' methods.
However, I obviously cannot simply write new U() in Fum to get an instance of SubFoo, so I want some static placeholder method that I can override. However, I obviously can't write public static abstract T create(); because of whatever reasons I can't fathom.
Therefore, I wrote a method in Fum that looks like:
#SuppressWarnings("unchecked")
protected static <V extends Foo<V>> V newSubFoo() {
try {//create() requires a constructed object to work.
return (V) Foo.class.asSubclass(Foo.class).newInstance().create();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
System.exit(1);
return null;
}//I don't expect this to work, but I don't know what to use before
} // the "asSubclass" call.
which manages to make the compiler shut up. However, this does not appear to be getting me anywhere.
In conclusion: Is there some way to construct a new object of the type U in Fum using a static method that can be overridden in SubFoo (preferably without writing a blank constructor in Foo)?
Firstly, sorry for the poor English, it is not my first language
How would one go about creating a object of a type from a subclass via the super class.
e.g.
if I have a super class:
public class superClassName(){
method(){
make object of subclass type used
}
and then I call the method in a subclass.
I'd like to have a an object created based on the subclass that's been called if that makes sense?
Using reflection may provide the quickest solution (this.getClass() returns the concrete subclass):
void method(){
//use default, no-arg constructor
superClassName newObject = this.getClass().getConstructor().newInstance();
}
Alternatively, your parent class can declare an abstract method that forces subclasses to provide a supplier:
public abstract class superClassName(){
abstract Supplier<superClassName> getInstanceSupplier();
void method(){
superClassName newObject = this.getInstanceSupplier().get();
}
}
And implement it as simply as:
public class SubClassName extends superClassName {
abstract Supplier<superClassName> getInstanceSupplier() {
return () -> new SubClassName();
}
}
I have an interface called Relation, implemented by a class BasicRelation, and extended by subclasses (e.g. ParentChild, Sibling, Spouse). While developing my code, I realized that I often need a method which takes a String representation of a relation to create it. For example:
public class ParentChild implements Relation extends BasicRelation {
// e.g. "Jack is Emily's father. Jill is her mother." will return the list
// <ParentChild(Jack, Emily), ParentChild(Jill, Emily)>
static List<ParentChild> fromSentence(String s) {
...
}
}
Now, since I find myself needing this method (fromSentence(String)) in every class, except perhaps in BasicRelation, I would like to move it up the hierarchy. The problem is that the internal details of the method is subclass-dependent, so I can't have it as a static method in the interface Relation or the superclass BasicRelation.
Unfortunately, in Java, it is also not possible to have a static abstract method.
Is there any way to ensure that every subclass of BasicRelation (or every class implementing Relation) implements fromSentence(String)? If no, should I be designing this in a completely different way? I guess this last question is more of a request for design-advice than a question.
Why does the static method need to be in the interface? What's stopping you from having a 'Utility' class and having the method in there?
public class RelationUtility {
public static BasicRelation relationFactory(String asString) {
....
}
}
As a static method, there is no reason other than access to private members, which can also be accomplished by by 'default' permissions on those members....
You can try making the BasicRelation class an abstract class and use an abstract fromSentence(..) method. This would require the ParentChild class to override and implement the fromSentence method because you can't create an object for ParentChild without implementing fromSentence()
public abstract class BasicRelation extends Relation(){
public abstract List<..> fromSentence(String s);
}
public class ParentChild implements Relation extends BasicRelation {
fromSentence(){
//parentChild class's implementation
}
}
If I understood right... you can try an approach like this
public class BasicRelation {
public abstract List<ParentChild> fromSentenceInSubclass(s);
public List<ParentChild> fromSentence(String s){
fromSentenceInSubclass(s);
}
}
And then you could have:
public class SubclassRelation extends BasicRelation {
public List<ParentChild> fromSentenceInSubclass(s){
// do subclass relation stuff
}
}
You will probably need to change the code a bit and add some Generics around to make it happen the way you want.
Sotirios Delimanolis Factory suggestion might also be an option.
You can have the abstract class BasicRelation include the static method which throws an Exception. That way you will be forced to override (shadow) the static method in the subclasses when you use it.
Something like:
public abstract class BasicRelation {
public static List<..> fromSentence(String s) {
throw new RuntimeException();
}
}
I have the abstract class Animal, and then I have classes like Dog and Cat, wich extend the class Animal.
I would like to make sure that all child classes of the parent class Animal have a static method: getProperties. Even when someone else, who doesn't have access to my code, implements a new Animal child class.
I want it to be static since all Animals of class Dog have the exact same properties (or you don't need a Dog to know how a Dog looks like genericly), and therefor it makes sense that it's a method called on the classtype, rather then a class instance.
Is this possible?
A static in Java means that the method (for example) in not related to any of the instances of the class. It's common to all the instances and it's implementation is just nested within the class.
As I read you problem, I believe you need an abstract method in the Animal class.
public abstract class Animal {
public abstract <some-return-type> getProperties();
}
In this case, every class which inherits Animal will have to provide an implementation of the getProperties method (which is not static in this case).
If you want it to be static, just make it so (within the Animal class), but then you will have a single and shared implementation.
The Java Object model doesn't support class-side inheritance (unlike Smalltalk or Ruby).
You have to explicitly implement a meta model of your domain, for instance, like this:
public abstract class AnimalDescriptor<T> { // or <T extends Animal>
public abstract List<String> getProperties();
public abstract T newAnimal();
}
public class DogDescriptor extends AnimalDescriptor<Dog> {
public static final DogDescriptor INSTANCE = new DogDescriptor();
public List<String> getProperties() { ... }
public Dog newAnimal() { return new Dog(); }
}
void doStuff(AnimalDescriptor<?> desc) {
desc.getProperties();
}
doStuff(DogDescriptor.INSTANCE);
This is just an example, you will have to adapt it to suit your needs. For instance, you might want to add a getDescriptor() method on the animal side.
No, not possible. There's no inheritance in static contexts. And no, there's no way to enforce a class to implement a static method.
That's not possible in Java, at much you could "hide" a static method, but not "override" it.
If you want to have each Animal class provide metadata about it, give it instance methods like getProperties, getNumberOfLegs, getLocomotionType, etc. You can implement these using static constants:
public abstract class Animal {
public abstract int getNumberOfLegs();
}
public class Dog {
private static final NUMBER_OF_LEGS = 4;
public int getNumberOfLegs() {
return NUMBER_OF_LEGS;
}
// ...
}
I suppose you wanted a Map of some sort for the getProperties method. The problem with that is that you must be very careful to make the map you return immutable. One mistake, and someone can change the static instance for everyone. making the method an instance method costs you almost nothing.
Static methods need to be able to run without you explicitly creating a new instance of the Animal class. You will have to fully implement Animal.getProperties().
I have the following classes.
public class Super{
public static void useSubClass(){
//I want to access the sub class object here, how.
}
}
public class Sub1 extends Super{
}
public class Sub2 extends Super{
}
I want to access the sub-class object from a static method in super-class. i.e. When I call Sub1.useSubClass() the method has access to Sub1.class and when I use Sub2.useSubClass(), I can access the Sub2.class.
Is there any way to access the sub-class object from super-class.
In general, you cannot do that from a superclass (and shouldn't!) because you won't know (and shouldn't assume anything about!) what classes will inherit from your superclass.
Depending on exactly what you want to do, there are alternatives, such as:
Use the template pattern to define "filler methods" that your subclasses must implement; these filler methods will be called by the template method in your superclass.
Define methods to be overridden by your subclass.
Define interfaces to be implemented by your subclass.
Update: As #JB Nizet has pointed out, I might have misread the question.
Here's something (very similar to the Observer Pattern) you can do if you wish to access subclasses from the static method in your superclass:
Define a static listener list in your superclass, call it List observerList
In the constructor of your superclass, add the class instance itself to that static observerList
For all subclasses, it is their responsibility to call super() from their constructors in order to register themselves to observerList (and unregister in deconstructor)
Then in your superclass's static useSubClass() method, you can iterate through that list of subclass instances, find the particular one you care about (maybe specified by some argument), and then do something with it.
Static methods are not inherited, and calling Sub2.useSubClass() is strictly equivalent to calling Super.useSubclass().
There is no way to get this information, because it doesn't exist. The compiler allows calling Sub2.useSubclass(), but translates it into Super.useSubclass().
public static void useSubClass(Super sub) {
if (sub instanceof Sub1) {
// Do something
} else if (sub instanceof Sub2) {
// Do something else
} else {
// Something else is extending Super
}
}
However, a better question is why? Can't you simply override the method in your subclass?
No you cannot because the super-class cannot know the methods of the sub-classes.
You should consider to create a new class which sees both super-class and sub-classes and implement the static method inside this new class
For the record, you could do this in Python, using class methods:
class super(object):
#classmethod
def usesubclass(cls):
print cls
class sub1(super):
pass
class sub2(super):
pass
Using this code, you could call sub1.usesubclass() or sub2.usesubclass(), and that would print the representations of the sub1 and sub2 classes, respectively:
>>> sub1.usesubclass()
<class '__main__.sub1'>
>>> sub2.usesubclass()
<class '__main__.sub2'>
Java, however, does not support such mechanisms, unfortunately. When you compile Sub1.useSubClass() in your example, the compiler will simply use Sub1 as the basic namespace to look up the the useSubClass() method in Super, but no information on that is actually compiled into code. In the resulting bytecode, the call is simply one directly to Super.useSubClass() and nothing more.
I sympathize with your plight, but Java is what it is. The closest thing you could come, I think, would be the following code:
public class Super {
public static <T extends Super> void useSubClass(Class<T> sub) {
}
}
And then call that method explicitly as either Super.useSubClass(Sub1.class) or Super.useSubClass(Sub2.class).
I figured something out. It works if implemented with care.
/** SuperClass.java **/
public abstract class SuperClass {
public static void printClass(){
System.out.println(new ImplementingClassRetriever().getCallingClass());
}
static class ImplementingClassRetriever extends SecurityManager{
public Class getCallingClass() {
Class[] classes = getClassContext();
for (Class clazz : classes) {
if (SuperClass.class.isAssignableFrom(clazz) && clazz != null
&& !clazz.equals(SuperClass.class)) {
return clazz;
}
}
return null;
}
}
}
/** Main.java **/
public class Main{
public static void main(String[] args) {
Sub.printClass(); //this does not work
Sub.testStaticCall(); //this works!! :)
}
}
class Sub extends SuperClass{
public static void testStaticCall(){
Sub.printClass(); //calling the method in the super class
}
}
This is just a toy example. The super class contains a static class that contains a method to retrieve the calling class.
In the subclass I have another static method which calls the superclass's method for printing the class name.
The Main class/function contains two calls to Sub's inherited and locally implemented method. The first call prints null, because the calling context (i.e. Main) is not a subclass of Super However the delegate method in Sub works because the calling context is now a subclass of SuperClass and hence the calling class can be determined.
Although You can create a reference to the super class and point it to any sub-class. This can also be done dynamically during run-time. This is a way of run-time polymorphism.