I want to call this.getClass() before calling the constructor with super(...).
abstract class A extends SuperClass {
public A() {
super(Manager.someOtherMethod(this.getClass()))
// Does not work: "Cannot reference 'Object.getClass()' before
// supertype constructor has been called".
}
}
I read about a workaround using static methods, but this.getClass() cannot be called from a static context.
This question depends on my previous question.
Thanks in advance for you answers :)
Whilst I am dubious about the need for this, you can do it by inserting the call to Manager.someOtherMethod into the constructor of the superclass:
class SuperClass {
SuperClass() {
Object result = Manager.someOtherMethod(this.getClass());
}
}
class A extends SuperClass {}
class Manager {
static Object someOtherMethod(Class<?> clazz) {
System.out.println(clazz);
return new Object();
}
}
would print out
class A
(if you create an instance of A)
Ideone demo
If SuperClass has multiple constructors, you can assign the result to a field in the superclass:
class SuperClass {
private final Object result = Manager.someOtherMethod(this.getClass());
SuperClass() { ... }
SuperClass(String someParameter) { ... }
}
then result will be available in both constructors.
I suggest you to refactor your code.
I assume that you have classes A1, A2 and A3 now.
You should introduce factory like this:
class AFactory {
public static A1 newA1() {return new A1(A1.class);}
public static A2 newA2() {return new A2(A2.class);}
public static A3 newA3() {return new A3(A3.class);}
}
Add parameter to classes A1, A2 and A3 constructors.
Add parameter to A constructor.
...what's the question? Do I understood correctly, do you want the class to be subclassed, and THAT class should be given to the super, but you don't want to call super in all the subclasses?
Indeed it can't be done this way as the class object is not constructed yet, and therefore it does not exist. So you cannot call a method on the object yet, or ask for the name, or whatsoever.
I think you're stuck with either a class passing on to super, or add a pretty useless public static class<? extends SuperClass> getThisClass() { ... } or am I missing something nice? if I do, pls comment, as I actually like to know myself too.
Just for curiousity I tried different ways which are stated here: Getting the class name from a static method in Java but the closest I got was getting that class test.staticgetclass.A in the middle class, but never its subclass name which I think you want to get.
Use a class literal as a constructor parameter
abstract class A extends SuperClass {
protected A(Class<? extends A> clazz) {
super(Manager.someOtherMethod(clazz));
}
Then in impl:
class B extends A {
public B() {
super(B.class);
}
Related
Okay, so recently I realized that I have some misunderstandings with extending and inheritance inside of java.
So far, my understanding states that you cannot do this
MySubClass myClass = (MySubClass) new MyClass();
That makes enough sense to me, but there are a few gabs and work-arounds that I don't know how to succeed in, such as if a person is trying to get a SubClass from a method that returns the SuperClass. For example:
public static MyClass getNewMyClass() {
return new MyClass();
}
And inside of MySubClass there are specific methods I want to access, such as
public void sayBye() {
System.out.println("Bye.");
}
So what I would think is I need to do is
((MySubClass) myClass).sayBye();
..but of course that throws a ClassCastException.
Summary/Question
So basically my question will be, how do I get the subclass of a returned class from a method, or is it possible?
Example: MyClass.getNewMyClass() returns a new MyClass, but I want to use the method sayBye() in its subclass, MySubClass.
More Information
The reason I'm asking this is because I'm trying to create an API for myself that basically will shorten the development of what I am trying to accomplish. In one of my classes, it contains a whole bunch of methods that returns MyClass. Some method examples could be public MyClass getNewMyClass() {}, public MyClass findMyClass(String name)() {} and so on.
But when I get to exending MyClass for some extra methods, I have about 10 methods from the superclass that returns MyClass, and all of that basically will leave me back to the beginning. Is there the possibility of returning Class<? extends MyClass> instead, or something similar?
Solved
Thank you everyone so much for your help, it is very much appreciated! So I basically decided to go with delegation. To solve my issue, here were all of my code and classes, that allowed me to access the superclass, but return the subclass.
Here was my InheritanceTest.java
public class InheritanceTest {
public static void main(String[] args) {
MyClass myClass = MySubClass.doMath();
if (myClass instanceof MySubClass) {
((MySubClass) myClass).sayBye();
}
}
}
And my MyClass.java
public class MyClass {
protected String name;
public MyClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static MyClass getNewMyClass() {
return new MyClass("Toshimaru");
}
public void sayHi() {
System.out.println("Hi.");
}
}
And finally, where it all seems to be resolved, MySubClass.java
public class MySubClass extends MyClass {
public MySubClass(String name) {
super(name);
}
public static MySubClass doMath() {
// Got the new instance of MyClass
MyClass myClass = getNewMyClass();
// And turned it into a MySubClass with myClass' properties.
myClass = new MySubClass(myClass.getName());
return (MySubClass) myClass;
}
public void sayBye() {
System.out.println("Bye.");
}
}
The trouble with trying to get a subclass from a superclass is you don't know what subclass it is. You could do an instanceof check first before casting and that would avoid the ClassCastException, but that is nasty. Ideally you should have your methods return objects that are as high up the hierarchy as possible but if you need a method that belongs to a subclass then that should be the return type of the method.
EDIT:
Your more information is a little vague, but this is legal:
public class MyClass {
public MyClass getNewMyClass(){
return new MyClass();
}
}
public class MySubClass extends MyClass{
#Override
public MySubClass getNewMyClass() {
return new MySubClass();
}
}
You can't make an Animal to bark, Only a sub class of Animal, Dog can bark.
In the same way, You can't invoke a sub class method on super class instance. Object oriented concepts are very much similar to real world.
MySubClass is an acceptable return for MyClass. I would instead return new MySubClass() which would then be able to call the subclass method. Polymorphism applies.
All Toyotas are Cars, but not all Cars are Toyotas. How does this relate here? In this example, Car is analogous to your MyClass and Toyota is analogous to your MySubClass.
If you create an object as a Car, you won't have access to the methods inside Toyota. However, if you create an object as Toyota, you do have access to the public (or protected) methods inside Car.
If you're the designer of MyClass and MySubClass, and you think sayBye() is a method that should be accessible at the parent level, then maybe you need to consider redesigning/refactoring and making sayBye() a method in your parent class.
This cast:
((MySubClass) myClass).sayBye();
does NOT always throw a ClassCastException, as you said, but it depends on what is the actual (more specific) type of the object referenced by the variable myClass.
If the variable MyClass myClass references an object of the class MySubClass, then the cast does not throw any exception.
But the point is that, if you want to call a method of an object, this method must be defined and implemented in the class (or some superclass) of that object, while you can NOT call a method on a object, where this method is only implemented in some of its subclass, because in this case that method is not present in that object (but only on object of its subclass).
I would like to make copy of SubClass object in BaseClass constructor. I need that the following code execute correctly.
class BaseClass{
BaseClass() {}
BaseClass(BaseClass base) {
//TODO: how to implement?
}
}
class SubClass extends BaseClass {
SubClass() {}
}
public class Test {
public static void main(String[] args) {
BaseClass sub = new SubClass();
BaseClass subCopy = new BaseClass(sub);
if (subCopy instanceof SubClass) {
// need to be true
}
}
}
Is it even possible? If yes how can I do it? Else how can I get similar effect?
It's not possible. A constructor of class A gives you an instance of A, no way to circumvent this. Why not instantiate the subclass explicitly?
Another possibility might involve a static factory method like:
public static BaseClass create(BaseClass input) {
// return BaseClass or subclass
}
It seems like you want the object of BaseClass to be an instance of SubClass which extends BaseClass.
Is it even possible?
-No. It is not possible.
The instanceof operator returns true if the variable on left side satisfies IS-A condition of the variable or class on the left side.
The SubClass IS-A BaseClass since it extends BaseClass. But the BaseClass can never be a SubClass, since it can't extend SubClass.
You seems to be having a design upside-down. If you need to do what you are asking then you need to re-think over your design. Ideally in your subclass constructor, you should be copying or initializing the base class properties by calling super().
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.
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.
class A {
public static void foo() {}
}
class B {
public static void foo() {}
}
I have Class clazz = A.class; or B.class;
How do I access this via "clazz" assuming it might be assigned either 'A' or 'B'
It is only possible to access those methods using reflection. You cannot reference a class directly, only an instance of type Class.
To use reflection to invoke methodname(int a, String b):
Method m = clazz.getMethod("methodname", Integer.class, String.class);
m.invoke(null, 1, "Hello World!");
See Class.getMethod() and Method.invoke()
You may want to think about your design again, to avoid the need to dynamically call static methods.
You can invoke a static method via reflection like this :
Method method = clazz.getMethod("methodname", argstype);
Object o = method.invoke(null, args);
Where argstype is an array of arguments type and args is an array of parameters for the call. More informations on the following links :
getMethod()
invoke()
In your case, something like this should work :
Method method = clazz.getMethod("foo", null);
method.invoke(null, null); // foo returns nothing
You cannot access static methods without an explicit reference to the class.
No inheritance here, sorry, so you must either do:
A.foo()
or
B.foo()
If you really need it, you will have to do a check:
Object o = .... // eith an A or B instance.
if( o instanceof A ) {
A.foo()
} else {
B.foo()
}
But why don't you just make those functions instance functions, and let them implement an interface?
Okey, you have a class object. Then do:
Class c = ...;
c.getMethod("foo").invoke(null); // null to invoke static methods
According to my lack of knowledge the need for the requested construct is given by the fact that an interface doesn't offer the possibility of static abstract methods. Here is an example:
public enum Cheese implements Yumy {
GOUDA(49),
ESROM(40),
HWARTI(38);
private int percentage;
private Cheese(int fat100) {...} constructor
public void yamyam() {...} // as in Yumy
public static Cheese getByFat(int fat100) {...} // no chance to be part
of interface
};
I hope this isn't making too many assumptions or deviating too far from your question, but if your two classes share a common supertype and creating an instance is tolerable then you can:
Implement a common interface
Create an instance of the object via myClass.newInstance() (class must have an empty constructor)
Call the static method from the instance object.
interface Foo {
void foo();
}
class A implements Foo {...}
class B implements Foo {...}
<T extends Foo> public void something(Class<T> clazz) {
T myInstance = clazz.newInstance();
myInstance.foo();
}
...
something(A.class);
It's a little bizarre but in my case it proved to be useful, and I began by asking the very same question that you did.