Overriding an instance method with static ones - java

I have a class that will be subclassed. All subclasses must contain a static method with the same signature, but differnt for each one.
I would like to have an abstract instance method in the superclass that subclasses will override, but it seems mot possible in Java, I wonder why.
A silly example:
Image{
abstract String getExtension();...
RGBImage extends Image{
static String getExtension(){return "RGB"};..
PNGImage extends Image{
static String getExtension(){return "PNG"};...

Have a look at this explanation. You could use the Builder pattern for your purpose.

As others have said, Java does not support overriding or abstract for static methods. However, I don't really understand what you would achieve with an "abstract" static method anyway.
The normal use of an abstract method is to force every subclass to implement a method with the same signature. But why would it even it matter for a static (hence non-polymorphic) method? If you forget to provide the method for one of the subclasses, EITHER it doesn't matter because you don't call it, OR it does matter but you'll get a compilation error at the point you try to call the missing method.
The only use-case I can think of where it might matter is if you are calling the method reflectively in a pseudo-polymorphic way. But if you are doing that you'd be better off using real polymorphism and instance methods.

I don't do much Java, but (using C++ logic) you could make the base class implementation a dummy implementation that cannot be executed.
static void DoStuff(arg_type arg)
{
std::cerr << "Method DoStuff() must be overriden\n";
::abort();
}
That isn't as good as an abstract method, but it will achieve some of the same results.

Unfortunately, this is not possible in Java. You have to make them instance methods to be able to define as being abstract.

It's not possible to override static methods as they pertain to a class, not an instance.
Furthermore, an instance method cannot be made static in the sub-classes as you suggest in your example.
Can you provide more information as to why all the subclasses need to have the same static method?

You want to override instance method with static method ? That makes no sense. Static methods are not polymorphic. How would you like to call it? It is impossible in Java to enforce class to have a static method with given signature.

as others have said, static is not polymorphic... it means it is the same for the class, not specific to an instance. i am not sure what you would accomplish by using a static method... but you could have have your extended method implementation return a static value:
public String getExtension() {
return STATIC_CONSTANT;
}
I guess it depends on what you are trying to accomplish with the static method. From your post: "Let me say, everything works OK implemnting a instance getExtension() method in each subclass. But the point is that the method is in fact static in the subclass, has no dependence on the instance. I know I can't do that, I only saying it seems no so strange idea to me."
The problem is you are asking for polymorphic behavior (a change in the behavior of a method for each subclass) from something that defines behavior for the class, not the instance. By definition, static cannot be polymorphic. I hope this helps you with your understanding here of why this is not possible.

The reason I want to have the abstract method declared in the superclass is because the class has to do some extra work with the result of the abstract method.
Lets put it simple even the example has no sense:
Image{
abstract String getExtension();
int process(){
return getExtension().length
}
The algorithm in process() is common for all subclasses XXXImage of Image, so its right place is the superclass.
Let me say, everything works OK implemnting a instance getExtension() method in each subclass. But the point is that the method is in fact static in the subclass, has no dependence on the instance.
I know I can't do that, I only saying it seems no so strange idea to me.

Yes thaks, this is what I'm doing, retun a static constat. In may case it returns the class object of a inner enum that lists the name of sections of a given file format: the file format of the subclass.
But you put it very clear in your example:
public String getExtension() {
return STATIC_CONSTANT;
}
I was expecting to be able to put "static" before String...

Related

Is putting static methods in interfaces a good practice?

Let's say I have a method getAverageDifficulty in my class Difficulty that goes like this:
public static Float getAverageDifficulty (List<Difficulty> difficultyList) {
...
return average;
}
My method obviously needs to be static, since it makes no sense requiring an instance of Difficulty. Now let's say I'm using an interface IDifficulty so I can change my implementation later. Obviously, I do want my getAverageDifficulty method to be available from IDifficulty, and, as I can't declare a static method abstract, the obvious option is to put getAverageDifficulty directly in my interface. My question is: am I making a mistake by putting that static method in my interface, which contains other Difficulty methods waiting to be implemented? Should I not mix static and "normal" interface abstract methods? Should I create DifficultyHelper class and put my method there?
Ultimately, this is a matter of style. However, if the only purpose of the helper class is to hold this method (and maybe a few similar ones), then you will be saving yourself one class definition by placing them in the interface:
As of Java 8, the restriction that interfaces cannot contain static methods was eliminated, so there is typically little reason to provide a noninstantiable companion class for an interface [Effective Java, 3rd edition].
Static methods in interfaces are similar to the default methods except that we cannot override these methods in the classes that implements these interfaces.so in my opinion its not not necessary to write static methods in interfaces until you want to prevent overriding.

How to call a singleton method from a Java POJO?

I wondered if it would be possible to call from a POJO a singleton bean's method through its interface. Maybe this idea is wrong or the architecture...but this is what I would like to accomplish if it is possible, because this is the architecture of the project.
I notice that when I call getInstance() (the method from the singleton's interface) from the POJO, there is an error occuring, telling me that the method has to be static, but if I make the method static, then I have to write the implementation in the interface and I can't get the singleton instance.
Your current approach with the interface is flawed. By default, all methods in an interface (up until Java 8) are static, and are implemented by instance methods in the implementing class.
This means, this is not an option. After all, you'll need to run the method to create an instance, meaning, you don't have an instance yet, so you have no instance to call it on.
Putting the same static method in an abstract class you extend, is also not a solution: a super class should never be aware of it's subclasses. If it is a static method (which it needs to be), you need to keep it in the class itself: a static method in an abstract class can (through an anonymous implementation of the abstract class) return an instance of the abstract class, but this is not the same as an instance of the subclass, which is what you are looking for.
In order to use this method for the subclass, you will need to inherit it from the super class. But, it will still return an instance of the super class. You'll need to overwrite the method in the subclass by the correct one, so the best solution is to add it straight in your Singleton class.
You are not allowed to have static methods in your interfaces (at least not until Java 8). Something like this is not allowed:
MyInterface var = new MyImplementingClass();
var.staticMethod();
Just remove the interface and do your static method call against the class where the static method resides.
Search a bit for the singleton pattern - the 'standard' way to do this involves classes and not interfaces, so rethink your design.
The idea seems to be wrong. A static method is always at a class level and hence you can never declare a method as static in a Java interface(you can do this in Java 8). However, this seems like the wrong design. If you really want to do something like this -
1)Make the Interface an abstract class.
2)Create a static method called getInstance();
3)Extend the abstract class in your POJO singleton class.
Hope this helps!!

Forcing subclasses to have a particular factory method or constructor

I am 70% confident that this is impossible, but is there a way to make sure that subclasses have a particular constructor or factory method?
In this case, I am trying to create a StringSerializable that would require subclasses to have the following methods
toString, which converts the object to a String.
fromString, which gets an instance from a String.
Obviously, in the first case, I can just make toString abstract. On the other hand, having a nonstatic fromString seems to be problematic. However, I can't create an abstract static method. I also do not think that a constructor is entirely appropriate.
You're correct; it's impossible to force it at compile time. There are various tricks you could do at runtime (such as using reflection in tests), but that's about it.
But ask yourself: why do you want to require that? You can't dynamically invoke a static method or constructor (except through reflection), so how exactly would you use those required factories, if you had them?
If it's just for consistency in the code (which is a good thing!), then you'll just have to ensure that consistency as you develop the code base. A comment in the base class can go a long way here, as can code reviews and other "soft" techniques.
If you plan to use the factories in reflection, then similar reflection can be used in tests to make sure that each subclass has the bits it needs.
Another option is to create a non-static factory:
public interface FooMaker() {
Foo create(String arg);
}
... and use that, rather than a static fromString method.
There again you have the same problem of "how do I ensure that every subclass has a FooMaker implementation?" and again I would say that you shouldn't worry about that. If you make the FooMaker the "starting point" of your code, rather than the subclasses, then it doesn't matter what the subclasses are doing; all that matters is that your FooMakers give you a way of going from string to Foos, and each Foo has a way of going back to a string.
the following code does ensure that every subclass needs to implement the static method, if the subclass does not implement the method it will fail when classes are constructed, as close as you can get to a compile time error, but not at compile time
the exception thrown is very clear and the programm will instantly fail when started
public abstract class Base {
static Functional test;
static {
if(test == null) {
throw new RuntimeException("You need to provide an implementation for the implemntMe method in class base");
}
}
private interface Functional {
Base implementMe(int whatever, boolean anotherParameter);
}
public static void main(final String[] args) {
}
}
the private interface construct ensures that only lambdas can be used to implement the method
a subclass would have to look like this
public SubClass extends Base {
static {
test = (int whatever, boolean anotherParameter) -> {
Subclass tmp = new Subclass();
//construct object
tmp.setWhatever(whatever);
return tmp;
}
}
}
lamdas are like inline methods that implement a functional interface, an interface which has only one abstract method
you can also declare the interface publicly at any other place and implement it with an anonymous inner class,
but my way makes sure that programers have to copy and paste code to reuse it,
or need to copy the object of Functional from another class

calling methods between classes

Is there a way to call a method in one class from another class. I could have say 5 classes and more than one may want to perform the same operation. So can I have one file (class??) with these common methods and call into that? If so what is the necessary modifier for these 'common' methods - public, final??
If anyone can point me to a suitable tutorial I would be grateful - in this instance I havent had much useful from Google
Thanks
Ron
This is a simple example for a (utility) class with a method that can be used from any other class:
public class Util {
public static int sizeOf(String input) {
return input.size();
}
}
To make it work "right out of the box": choose public and static as access modifiers for the method. Just like all methods from the well known java.lang.Math class.
I'd go with a general tutorial on OOP and how to use classes, e.g.
http://download.oracle.com/javase/tutorial/java/javaOO/classes.html
Basically you can call any method from another class, as long as it's public. If the method is static, you don't even need to instantiate it. But read some tutorials to get the basic idea of OOP instead of just looking for a solution for your specific problem, it'll help a lot more!
You probably want to create a "Utility" class. You can use the static keyword to make your methods static:
public UtilityClass {
public static int myMethod(String arg) {
}
}
result = UtilityClass.myMethod("sdfs");
In the implementation of the static methods you can't use local fields, unless you also mark them as static.
You can either make these methods public static.
An other way would be to pass instances of these other classes into your class. Maybe as a method parameter, set-method or parameter of the constructor.

why we should not use static and abstract for a single method?

why we should not use static and abstract for a single method?
the static keyword is defined so that a method can be called by a class name rather then an object. that means the method has to have some sort of definition. but abstract means you do not have any details about what the method does, it is as it says **Abstract**. When you inherit or extend a class you can then define the method.
Think of an interface.
If you are asking about having a static method inside of an abstract class, that is a different story. An abstract class is essentially as mentioned an interface and contains just a template of say functions that you must later on implement by inheriting / extending the class. Once you extend that class the static method does not come along with it (that is by default unless the access modifier is public / protected).
A static method is not inherited. Therefore, making it abstract is a nonsense.
The abstract keyword means that child classes must override the method - this is (one of the ways) Java supports polymorphism. If you want to make it so that subclasses cannot override the method you mark it final. So it would be impossible to have an "abstract final" method since they are the exact opposite of each other.
the static keyword implies final as well - all static method are also final. Thus it is impossible to have a method that is both static and abstract since you would be able to make a method that is abstract and final.
The reason for static being final is that it is bound to the class instead of the instance. That means that the compiler looks it up at compile time rather than runtime to determine which method to call. The reason what it is like that? Arbitrary decision that the designers of Java made - they could have allowed static method to be overridden but decided not to. I don't have any particular insight as to why the chose one over the other unfortunately.
As others have said, static+abstract is nonsense in Java. But there have been (rare) occasions where I've wished I could do just that.
The result I was looking for was basically to say that... "all concrete classes that extent this abstract class (or implement this interface) must provide a static method with this signature." This capability would allow these classes to provide meta-information about themselves.
Normally I have ended up with an instance method in these cases. If you stipulate that concrete implementations must support the default (no-arg) constructior, you can do...
MyInterface obj = MyClassThatImplementsMyInterface.newInstance();
obj.invokeTheMethodIWishWasBothStaticAndAbstract();

Categories

Resources