I have an abstract class A
I have about 10 classes that extend A
Class A has one or two static methods and it makes sense that these are static, because they belong to the 10 classes, NOT instances of them. One static method e.g. is called getAllFromX, which gets all all instances of the class from X, whatever that may be, it may be a server, well it actually is, but it doesn't matter. So you see it makes sense these methods are static and are not bound to an instance.
At the same time class A has a NON-static abstract method, each subclass overrides this method (just returns a string). I cannot make it static because static methods cannot be overridden (...).
To summarize: abstract class A has a static method and a abstract non-static method, that is overriden by the subclasses. I cannot make the second method static because it must be overriden. On the otherhand I could make the first method non-static, but it would be very ugly and bad programming style, so I'll leave it that way.
The catch? The static method in class A must get the value the non-static method returns (for the subclass the static method is inherited from, of course).
Is the "easiest" way to use reflection to get this done? I mean...really?
Like e.g., I get the class the static method is in:
Class<?> cl=new Object(){}.getClass().getEnclosingClass(); (a hack I found here, thank god...)
I then use getConstructor to construct an object of this subclass.
And then I use this object to call the non-static method.
Really?? Can it not be done easier? I mean that is if I want to design my program conceptually correct...
Coming from C# I don't like that (and the type erasure thing). It is just ugly. Doable but ugly. And a big stumbling block, at least for beginners. EDIT: after reading it again, I'd add: /rant end. Sorry, but I actually care.
I think what you in fact need is the following:
public class A {
public static Set<A> getAllFromX() {
...
}
}
public class B extends A {
public static Set<B> getAllFromX() {
...
}
}
public class C extends A {
public static Set<C> getAllFromX() {
...
}
}
(Just as the valueOf() and values() methods in enums, which is redefined in every Enum subclass, because static methods can't be inherited)
In this case, each class has its own static method doing whatever it wants. But your question doesn't make much sense because it says:
The static method in class A must get the value the non-static method returns (for the subclass the static method is inherited from, of course).
Indeed, the static method is not inherited by the subclass. Static methods are never inherited. If you define a static method foo() in A, and call
B.foo();
the compiler doesn't refuse to compile it, but it translates it to
A.foo();
So, there's no way to do in foo() something that depends on the class on which foo() is called, since it's always A.
You can always use reflection to invoke a method using class name e.g.
Object objectX = ClassX.class.newInstance();
//get your method passing argument types as second param
Method method = ClassX.class.getDeclaredMethod("methodX", null);
//invoke your method passing arguments as second param
method.invoke(objectX, null);
Since you mentioned your static method doesn't use any instance but you are using reflection to get the instance hence I am really not sure, how does it fit in your requirement though.
I think making it as an implemented method (non-static) in your abstract class is a better choice. That way you implement it once but its available in in all your 10 extending classes.
I think your problem is one of larger design. A different object should be responsible for retrieving instances of A or its subclasses. As you can see, relying on a static method to be replaced by subclasses does not work well. Without knowing more about the problem domain, it's hard to give a good answer, but I would consider something similar to the Abstract Factory pattern.
Broadly speaking: Define an abstract class, AFactory, with a method Collection getInstances(). Extend AFactory for each of the concrete subclasses of A you need to return and implement that logic in the overridden getInstances() method as appropriate. You may also provide a static method on the abstract AFactory, getFactory(Class), to get the appropriate factory subtype at runtime.
Related
Suppose I have these classes:
public class ChildClass extends ParentClass
{
// some class definition here
}
public abstract class ParentClass
{
public static void printClass()
{
// get the class that extends this one (and for example, print it)
}
// some class definition here
}
Lets say when calling ParentClass.printClass() I want to print the name of the class (like doing System.out.println(ParentClass.class)). When then extending ParentClass (for example like in ChildClass) and calling ChildClass.printClass(), I want it to print the name of the extending class (like doing System.out.println(ChildClass.class)). Is this somehow possible?
I've found a way to get the class from inside a static method by using MethodHandles.lookup().lookupClass(), but when using it inside of ParentClass.printClass and extending ParentClass, then calling printClass on the extending Class, I always get the class of ParentClass.
static methods are best thought of as living entirely outside of the class itself. The reason they do show up in classes is because of the design of java (the language) itself: Types aren't just types with a hierarchy, they also serve as the primary vehicle for java's namespacing system.
Types live in packages, packages are the top level namespace concept for types. So how do you refer to a method? There's only one way: Via the type system. Hence, static methods do have to be placed inside a type. But that's about where it ends.
They do not inherit, at all. When you write:
ChildClass.lookupClass()
The compiler just figures out: Right, well, you are clearly referring to the lookupClass() method in ParentClass so that is what I will compile. You can see this in action yourself by running javap -c -p MyExample. The same principle applies to non-static methods, even.
For instance methods, the runtime undoes this maneuvre: Whenever you invoke a method on any object, the runtime system will always perform dynamic dispatch; you can't opt out of this. You may write:
AbstractList<String> list = new ArrayList<String>();
list.sort(someComparator);
and you can use javap to verify that this will end up writing into the class file that the method AbstractList::sort is invoked. But, at runtime the JVM will always check what list is actually pointing at - it's an instance of ArrayList, not AbstractList (that's obvious: AbstractList is abstract; no object can ever be directly instantiated as `new AbstractList). If ArrayList has its own take on the sort method, then that will be called.
The key takeaway of all that is: Static methods do not inherit, therefore, this dynamic dispatch system is not available to them, therefore, what you want cannot be done in that fashion.
So what to do?
It feels like what you're doing is attempting to associate a hierarchy to properties that apply to the class itself. In other words, that you want there to be a hierarchical relationship between the notion of 'ParentClass's lookupClass method and ChildClass's lookupClass method - lookupClass is not a thing you ask an instance of ChildClass or ParentClass - you ask it at the notion of the these types themselves.
If you think about it for a moment, constructors are the same way. You don't 'ask' an instance of ArrayList for a new arraylist. You ask ArrayList, the concept. Both 'do not really do' inheritance and cannot be abstracted into a type hierarchy.
This is where factory classes come in.
Factory classes as a concept are just 'hierarchicalizing' staticness, by removing static from it: Create a sibling type to your class hierarchy (ParentClassFactory for example):
abstract class ParentClassFactory {
abstract ParentClass create();
abstract void printClass();
}
and then, in tandem with writing ChildClass, you also write ChildClassFactory. Generally factories have just one instance - you may want to employ the singleton pattern for this. Now you can do it just fine:
class ChildClassFactory extends ParentClassFactory {
private static final ChildClassFactory INSTANCE = new ChildClassFactory();
public static ChildClassFactory instance() { return INSTANCE; }
public ParentClass create() { return new ChildClass(); }
public void printClass() { System.out.println(ChildClass.class); }
}
// elsewhere:
// actually gets the ChildClassFactory singleton:
ParentClassFactory factory = ....;
factory.printClass(); // will print ChildClass!
Quoting #RealSkeptic:
Static methods are not inherited. The fact that you can call ChildClass.printClass() is just syntactic sugar. It actually always calls ParentClass.printClass(). So you can't do something like that with a static method, only an inheritable non-static one.
I have recently stubled upon something that has always annoyed me.
Whenever I want a method to be invoked in all classes that have a certain interface, or if they are extensions, I would like to have a keyword that does the opposite of the keyword super. Basically, I want the invocation to be passed down (if a class inherits a method, and the method in the superclass is called, it will be called in the subclass as well). Is there anything that resembles what I am asking for?
EDIT:
The contemporary methods I am using are efficient, but not as efficient as I would like them to be. I am only wondering if there is a way of invoking a method, that has been inherited, from its superclass/superinterface. The last time I was looking for this, I did not find it either.
NOTE: All of the subclasses are unknown, hence impossible to utilize. The only known class is the superclass, which is why I can't invoke it. This can be solved using the Reflections API, which I am currently using. However, it does not always comply with what I am searching for.
Every method in Java is virtual with the exception of static methods, final methods and constructors meaning that if a subclass implements the method being invoked, the subclass's implementation will be called. If the subclass wishes to also invoke the immediate superclass method, that is accomplished via a call to super.
This is very common with abstract classes where some base class is utilized by a framework, but clients are expected to override. For instance:
public abstract class Drawer{
public void draw(){
//setup code, etc common to all subclass implementations
doDraw();
}
protected abstract void doDraw();
}
public class CircleDrawer extends Drawer{
protected void doDraw(){
//implementation of how to actually draw a circle
}
}
Now, when you have an instance of CircleDrawer and you call draw(), the superclass Drawer.draw() method will be invoked that is, in turn, able to call CicleDrawer.doDraw().
Edit Now, if CircleDrawer was this:
public class CircleDrawer extends Drawer{
public void draw(){
//do stuff
}
protected void doDraw(){
//implementation of how to actually draw a circle
}
}
Any invocation of Drawer.draw() on an instance of CircleDrawer will always invoke the CircleDrawer.draw() method.
If you mean something like this:
class A {
public void func1(){
//do stuff
subclass.func1();
}
}
class B extends A{
public void func1(){
//do more stuff
}
}
class C extends A{
}
What happens when I call new C().func1()? Remember, func1 is not abstract and therefore, you cannot require classes to define it.
A better solution is to do the following:
abstract class A {
public void func1(){
//do stuff
func2();
}
public abstract func2();
}
class B extends A{
public void func2(){
//do more stuff
}
}
Hence, you require your subclasses to define a function that you can call from the super class.
The is no such a thing. When calling an overriden method in Java, the child-most class's method will be always called. If you want to call parent methods as well, you need to use super.methodCall() in every class's method of your hirearchy.
Unfortunately, I don't believe the thing you are trying to do is as possible as you may think. It's not quite that easy to invoke your subclasses from the super class, because not all subclasses may behave in the same way so a generic keyword for that functionality would wreak havoc! Although, by the phrasing of "Basically, I want the invocation to be passed down." it sounds like what you want is normal inheritance.
Just define the most generic similarities that all subclasses have in common in the superclass, then simply start each subclass definition of the method with super()
I don't mean to point out the obvious, but OO was designed for that and not for what you are asking. I doubt you'll be unable to find a way to do what you want within the typical arsenal of OO concepts
I think you got confused describing what you need, I don't think this:
Whenever I want a method to be invoked in all classes that have a certain interface, or if they are extensions
Is the same as this:
I would like to have a keyword that does the opposite of the keyword super
From what I understand, in the first one, you are referring to calling a method for all instances of a base class and its subclasses. For the second one, calling a subclass' method is exactly calling that method on a subclass which has probably overriden it.
I'm not sure what you are trying to do, maybe you should clarify with an example. Most likely, yours is a design problem which is solved in a different way than the one you are proposing. However, a "solution" came to mind when reading your question.
I'm a little more experienced with C# and python than with Java (and not even that much), but I'm sure more experienced programmers won't hesitate to correct me if I said stupid things.
You should have some kind of collection of objects of type of the base class and call that method, on each object, which each subclass must have overriden.
Maybe using the observer pattern, which is commonly used to reproduce event triggering, you can make all instances of a base class and its subclasses execute a "callback" whenever you want.
I am a noob and I need some help.
So I have this abstract class with a private variable. I also have a method named getThing() to return that.
I have a class that extends that abstract class, and it too has a private variable and a method that overrides the original to get the value from the abstract class.
Well the only way to be able to access both values is by creating a second method in the subclass called getSuperThing, and using the super in that. Well I was just wondering out of curiosity if there was some easier way to do that and be able to access the abstract classes method by doing something like objectNae.super.getThing().
Thanks ;)
The variable is private and so can only be referenced by the containing (abstract) class. As you have stated, from a subclass, you can invoke the superclass method (rather than the overridden one).
If you want to make the variable accessible from the subclass directly (without requiring the accessor method), make it protected instead. Here is the documentation on Controlling Access to Members of a Class.
If I understand your question correctly, then you just shouldn't override the abstract class' method in the concrete subclass. No need to, unless you need the subclass to return a different value than that returned by the abstract class (and that would suggest poor design).
Rather, the abstract class' method will be accessible as a method of the subclass.
So, if you have:
public abstract class AbstractClass {
private int value = 3;
public int getValue() {
return value;
}
}
public class ConcreteClass extends AbstractClass {
}
then you should be able to do:
new ConcreteClass().getValue()
I don't think you have other ways than calling super.getThing() in the subclass's getThing() or getSuperThing() method. Abstract class must be subclassed before being used.
Ok so I know that you can't have an abstract static method, although I see this as a limitation personally. I also know that overriding static methods is useless because when I am dealing with say MyList<T extends ObjectWithId> and my object has an abstract class with a static method that gets overridden in it's subclasses, T doesn't exist at runtime so ObjectWithId's static method would be called instead of the subclass.
So here is what I have:
class PersistentList<T extends ObjectWithId> implements List<T>{
}
where ObjectWithId is:
abstract ObjectWithId{
public abstract long getId();
}
Now the issue is that my PersistentList is meant to be stored on hard disk, hence the name, and in reality will only store ids of objects it holds. Now when I want to implement the
#Override
public T get(int index) {
}
method of PersistentList, what I want is for my program to use the id it has stored for index and call a static method objectForId(long id) which would be implemented in each subclass of ObjectWithId. It can't be a instance method because there is no instance yet, the point is to load the instance from the hard disk using the id. So how should it be implemented? One option is to have ObjectWithId have a constructor ObjectWithId(long id) implemented in each subclass, but T doesn't exist at runtime so how would I instantiate it? I know I could pass Class<T> object in the constructor of PersistentList but I would prefer if the constructor did not have any arguments, but I don't think there is a way to get the class of T without explicitly passing it in right?
I hope this is a better explanation, sorry for the ambiguous question I started with.
While passing the Class<T> as a constructor argument, it does not really solves your problem. You then have access to the class, but to get access to the static method defined on the class you will have to use generics (unless somebody else knows a way to call a static method defined on a class from a Class object).
I would define a new generic interface which contains a generic method objectForID, something like
public interface ObjectRetriever<T>{
public T objectForID( long aID );
}
and adjust the constructor of the PersistentList to take such a ObjectRetriever instance as parameter. This ObjectRetriever can then be used to restore the objects based on their ID.
While it always seems easier to start out with static methods, I've found it to usually be beneficial to avoid static methods for just this reason, and to use instance methods by default.
The advantage to this is extensibility. Besides allowing for inheritance and avoiding the "limitations" you mentioned, it provides for extensibility - without needing to redesign things and change APIs later. For example, "this class does exactly what I need, but I wish I could change only this one portion of functionality". If there are static methods calling other static methods, there is no good way to do this. If all the methods are non-static - I can subclass that class and override only the portion of functionality required.
The other (somewhat-related) limitation to static methods is that they can't be used to implement interfaces.
In summary, I prefer to reserve static methods for "utility methods" where the function that they are performing is really clear-cut, and there isn't any feasible future reason why an alternative implementation would need to be provided.
In object-oriented paradigm, a virtual function or virtual method is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature to provide the polymorphic behavior.
According to the definition, every non-static method in Java is by default virtual method except final and private methods. The method which cannot be inherited for polymorphic behavior is not a virtual method.
An abstract class in Java is nothing but the pure virtual method equivalent to C++.
Why do we say that a static method in Java is not a virtual method? Even if we can override the static method and consequently it may give some advantages of the polymorphism and also a static method in Java can be invoked mostly with it's associated class name but it is also possible to invoke it using the object of it's associated class in Java in the same way that an instance method is invoked.
You can't override static methods. They are bound at compile-time. They are not polymorphic. Even if you try to invoke it as if it were an instance method (which IMO you shouldn't do) it's bound to the compile-time type of that expression, and the execution-time value is completely ignored (even if it's null):
Thread otherThread = null;
otherThread.sleep(1000); // No errors, equivalent to Thread.sleep(1000);
This behaviour can be very confusing for a reader, which is why at least some IDEs allow you to generate warnings or errors for accessing static members "through" a reference. It was a flaw in Java's design, pure and simple - but it doesn't make static methods virtual at all.
Suppose you have class A
public class A
{
public static void doAStaticThing()
{
System.out.println("In class A");
}
}
And B
public class B extends A
{
public static void doAStaticThing()
{
System.out.println("In class B");
}
}
And a method in another class like this:
public void foo()
{
B aB = new B();
bar(B);
}
public void bar(A anA)
{
anA.doAStaticThing(); // gives a warning in Eclipse
}
The message you will see on the console is
In class A
The compiler has looked at the declared type of anA in method bar and statically bound to class A's implementation of doAStaticThing(). The method is not virtual.
It's simple, a static method cannot be overridden by an inheriting class, since it's not inherited. So it's not virtual.
What you call "overriding a static method" is actually only defining another static method on another class. It'll only "hide" (and that's actually a much stronger word than what'd be actually true there) the other one, not override it.
An abstract class in Java is nothing but the pure virtual method equivalent to C++.
A class is not a method. An abstract class doesn't have to have "virtual" or abstract methods, or even any methods.
Something C++ developers put down Java features as just like C++ renamed without understanding the differences. ;)
Why do we say that a static method in Java is not a virtual method?
Not sure who says this, but static methods are not polymorphic.
Even if we can override the static method
We can't, you can only hide or overload a static method.
Whether you use the class or sub-class or instance to invoke a static method the actual class or instance is ignored. e.g. you can do
((Thread) null).yield();
Because polymorphism applies to objects, while a static method doesn't relate to any object (but to a class).