I have an abstract class that performs basic operations, now I want to force every derived class to have a method "check", but the point is I know nothing about this method. For example, the abstract class:
public abstract class Service<T extends Transport> {
public T getTransport(int id) {
[...]
}
public abstract boolean checkTransport(T transport, ...);
}
and two implementing classes:
public ServiceAAA extends Service<ClassA> {
public boolean checkTransport(ClassA t) {
[...]
}
}
public ServiceBBB extends Service<ClassB> {
public boolean checkTransport(ClassB t, Integer value, Integer otherValue) {
[...]
}
}
The ServiceBBB needs two parameter to check the object t of class ClassB.
Of course it's not working, is there a way to force the subclass to implement the checkTransport method without using the "Object ... " notation?
No, there isn't.
Let's pretend there were a way. How would you invoke this method, either from the abstract Service class, or from any call site that had a reference to this object typed as Service<...>? There'd be no way of knowing what the specific subclass's method expects, and thus no way of invoking the method.
One way around this is to pass the checker in as a class to Service; that is, to use composition instead of inheritance. If you do that, you can have the checker's interface take no extra arguments at all (a Predicate might work, for instance), and the specific subclasses that implement that checker could have the arguments passed at construction time.
Related
public abstract AbstractGameStats<A extends GameStats> {
public abstract A addGameSpecificStats(final A gameStats, final LiveStats liveStats);
}
public abstract class LiveStats { // }
public class FootballStats extends LiveStats { // }
public class FootballLiveGameStats extends AbstractGameStats<FootballGameStats> {
#Override
public FootballGameStats addGameSpecificStats(final FootballGameStats gameStats, final FootballStats footballStats) {}
}
Doing this tells me im not overriding the parent method because in addSpecificGameStats, im passing in the subclass of FootballStats rather than the LiveStats parent class.
I dont understand what the problem is here. Why cant i just pass in the base type? Isnt this the whole point of polymorphism?
addGamespecificStatstakes a LiveStats argument (second). Any method overriding this must also accept LiveStats. Your overriding method only accepts FootballStats but not BaseballStats (assuming this is also a subclass of LiveStats).
The point is: An overriding method may accept more but not less. Imagine:
AbstractGameStats<...> a = new FootballGameStats();
a.addGameSpecificStats(gameStats, baseballStats);
This would be legal because AbstractGameStats.addGameSpecifigStats accepts LiveStats and all subclasses. But your overriding method would not.
Overridden methods must have the same name, number and type of parameters, and return type as the method they override - that's the rule. (You can do however return a sub-type of the type that the overridden method returned, but you don't need this).
What you can do is just use your second argument as is, and downcast when necessary (Ideally you should aim to handle your objects by the interface and avoid the casting).
You can also add a further template argument to provide more specialized handling or type safety, like this:
public abstract class AbstractGameStats<A extends GameStats, B extends LiveStats> {
public abstract A addGameSpecificStats(final A gameStats, final B liveStats);
}
I realize the title is kind of messy, but that's the best I could come up with.
Below is a minimal example of what I wish, but am currently failing to do.
public class ObjectA {}
public class ObjectB extends ObjectA {}
public interface HandlerInterface<T extends ObjectA> {
public T easyToOverride();
public List<T> hardToOverride();
}
public class HandlerA implements HandlerInterface<ObjectA> {
public ObjectA easyToOverride() {
return new ObjectA();
}
public List<ObjectA> hardToOverride() {
return new ArrayList<ObjectA>();
}
}
public class HandlerB extends HandlerA implements HandlerInterface<ObjectB> {
/*
This method ovverides its super method with ease since its return
type directly inherits from the super class's return type
*/
public ObjectB easyToOverride() {
return new ObjectB();
}
/*
This method is NOT accepted by the Java syntax since List<ObjectB>
does NOT directly inherit from List<ObjectA>
The method signature for hardToOverride() clashes with the signature
in the super class and is not overridden because the return types
don't obviously inherit each other
*/
public List<ObjectB> hardToOverride() {
return new ArrayList<ObjectB>();
}
}
Ignore that these classes should be in their own files and that I have not included their imports. I just put it like this to make it easier to read.
As you may have understood by the comments in the class HandlerB, the method hardToOverride() is not accepted (throw this code into your IDE and watch it scream).
I realise I could just return a List<Object> and type cast the contents of the returned List object to the type that I personally know the specific handler instance returns (ObjectA or ObjectB), but that would mean that anyone using these methods has to understand the inner workings of them, and I do not like that.
What I want is to be able to override the List<ObjectA> hardToOverride() method with a method List<ObjectB> hardToOverride() without losing the hard typing that these methods provide.
So my final question is:
Is there any way to keep all of these interfaces, inheritances and overrides without loosing the strong typing they provide in my example code?
If not, what is a better way to achieve a similar set of classes and interfaces that actually works?
Your code is accepted if you declare HandlerA with a new generic even if this is never used really:
public class HandlerA<T> implements HandlerInterface<ObjectA> {
//....
}
NOTE: This is to be considered just a workaround but as result your example code will work as you asked. Moreover, even if HandlerA declares a generic, you can anycase instantiate it also without brackets:
ObjectA objectA = new HandlerA();
I have these interface and classes:
public interface AlternateLight {
public String change(long time);
}
public abstract class AbstractLight {
public String change(int time) {
return "AbstractLight Method was used";
}
}
public class DistinctAlternateLight extends AbstractLight implements AlternateLight {
public String change(long time) {
return "DistinctAlternateLight Method was used";
}
}
Now I call the method change() with following main-method:
public class WhatUsedTest {
public static void main(String[] args) {
AlternateLight al = new DistinctAlternateLight();
System.out.println(al.change(100));
}
}
It prints "DistinctAlternateLight Method was used", but why? I thought since I didn't put a "L" behind the 100 as argument, it would call the method of the abstract class, because its method takes integers. With missing out on the "L", I guessed the compiler wouldn't handle the 100 as a long value and call the method taking longs, but it does. Why is that so?
It's due to the polymorphism, if you declare your variable with AlternateLight class and this type has only acces to change(long time).
be careful. If you use interface as reference type and assign an object of implementing class to it then you can call only those methods that are declared inside the interface. This is quite obvious because the implementing class can define methods of its own that are not a part of the contract between the interface and class. So, to call those methods you have to use the class as reference type as following:
DistinctAlternateLight al =new DistinctAlternateLight();
The method with the closest match to your type arguments will be used.
But for compatible numerical, the deepest declared one.
You can also see that the type of "al" object is an interface type, so you can`t call the method from super class without casting, you also can`t call any method from AbstractLight without casting. You can only call methods there were declared in interface class. In that case, compiler will favour the method from the interface class.
You can force the compiler to call a method from abstract class if you write something like that:
System.out.println(((AbstractLight)al).change(100));
I haven't quite found an elegant way to solve this issue. I have an abstract class that several other classes are inheriting with an abstract method that can contain anywhere from zero to 4-5 arguments of varying types.
public abstract class Item {
public abstract void use();
}
For instance, I have a Book class that inherits this and takes no arguments when overriding use(), I have a Key class that inherits and takes a String and a Queue as arguments when overriding, etc...
I've tried using generics but I have to input the number used, such as Item, when it actually depends on the class.
public abstract class Item<T,U> {
public abstract void use(T arg1, U arg2); //Number of arguments/types could be more or less
}
I've tried sending a variable list of Objects but the object types are always variable and I've unsure as to the syntax to receive in the inheriting classes.
public abstract class Item<T> {
public abstract void use(T... arguments);
}
public class Book extends Item<?> {
public void use(?);
}
public class Book extends Item<String, Queue> { //Wrong number of arguments since I can't use Item<T...>
public void use(String str, Queue q); //fails
}
I may just be doing something wrong - can anyone offer any assistance or insight?
I've struggled with the same question, and there's not a perfect answer, but I can give you a few things to consider. First, you're basically trying to do something that is inherently against Object Oriented Programming, which is that you're trying to create a variable interface. The point of an interface is that code that gets an abstract version of the object (the Item rather than the Book, for example), knows how to invoke the use() method. This means that they must know what can be passed to the use() method. If the answer depends on the implementation of the abstract class or interface, then you need to ensure that the code using it actually knows what kind of implementation (Book, etc.) that it's using, otherwise it's not going to know how to invoke use() with the appropriate parameters anyway. It sounds like you need to refactor your code, in all honesty.
However, there is a way to answer your question as stated without refactoring the architecture. You could create a class that's data is all of the different types of parameters that could possibly be passed to the use() method, have the calling code set the fields of that class, and then pass that to the use() method. For example:
public class UseParameters {
private String string;
private Queue queue;
// Any other potential parameters to use(...)
public void setString(String string) {
this.string = string;
}
public String getString() {
return string;
}
// All of the other accessor methods, etc.
}
Then, you could define the use method in Item like this:
public abstract void use(UseParameters params);
And any code using an Item would have to set the parameters of the object appropriately:
Item item = // However you're going to get the item
UseParameters params = new UseParameters();
params.setString("good string");
params.setQueue(new Queue());
item.use(params);
I just want to point out that if the code above knows the Item is a Book (which is how it knows to set the String and Queue, then why not just get a Book and skip needing an abstract class with a variable use() method altogether? But I digress. Anyway, the Book would then implement the use() method like so:
#Override
public void use(UseParameters params) {
if(params.getString == null || params.getQueue() == null)
// throw exception
// Do what books do with strings and queues
}
I think that gets you what you want, but you should consider refactoring, I think.
What you want is the Value Object Pattern.
Define a class that encapsulates the various parameter types into one value object, and have the abstract method accept a parameter of this type. Each variation of parameters you were considering would have its own value class.
Then simply add a generic type to the class and have the abstract method accept a parameter of that type:
public abstract class Item<V> {
public abstract void use(V v);
}
To use it, suppose MyItem needs a value object of type MyValueClass:
public class MyItem extends Item<MyValueClass> {
public void use(MyValueClass v) {
}
}
If the types to be used as argument are always variable I don't see a reason to use generics. Just use plain Object type:
public abstract class Item {
public abstract void use(Object ... arguments);
}
public class Book extends Item {
public void use(Object ... arguments) { ... }
}
The best approach I can think of is to group the items according to the behavior of their use() method.
Example
public abstract class QueueableItem {
public abstract void use(String, Queue);
}
public abstract class OrdinaryItem{
public abstract void use(String);
}
If the grouped items share a common behavior (common as in same method signature & return value), you can define and extend a parent class that will contain the definition of this common behavior.
Yes, we can provide parameters to abstract method but it is must to provide same type of parameters to the implemented methods we wrote in the derived classes.
Is it at all possible to "override" a private method of a super class in Java?
The class whose method I wish to override is a third party class so I cannot modify the source. It would be ideal if there were some way to reflectively set a method on a class.
Alternatively, if it is possible to intercept a private method of a third party class then this would be suitable.
YES. You can do it with AspectJ. It is not a true override but result will be so.
Here your super class;
public class MySuperClass {
private void content(String text) {
System.out.print("I'm super " + text);
}
public void echo() {
content("!");
}
}
Create an interface which contains similar method;
public interface Content {
void safeContent(String text);
}
Create an aspect that forces super class to implement that interface and add an around adviser to call it.
public privileged aspect SuperClassAspect {
void around(MySuperClass obj)
: execution(* content(String)) && target(obj) {
Object[] args = thisJoinPoint.getArgs();
((Content) obj).safeContent((String) args[0]);
}
// compiler requires
public void MySuperClass.safeContent(String text) {}
declare parents :MySuperClass implements Content;
}
Create your child class that extends super and implements that interface.
public class Overrider extends MySuperClass implements Content {
public void safeContent(String text) {
System.out.print("Not that super " + text);
}
}
Now if you construct a Overrider object and invoke echo method, you will have an output of Overriders safeContent's method.
Is it at all possible to "override" a private method of a super class in Java?
No
I don't think using Reflection there would be a tweak , it will break OOP there
You do not have a legal way to do this. But I can suggest you the following solutions.
Do you really wish to override this method? Try to think about other solution.
Java checks access permissions during compilation only. Are you surprised? I was surprised very much to find out this fact. So you can create skeleton of the third party class (even with empty implementations.). The interesting method should be protected instead of private. Now write your subclass and compile it against your stub. Then package only your subclass and try to run it with the "real" class. It should work. I have not tried this trick with inheritance but I have tried it when I had to access private method or field and it worked fine for me.
Try to use dynamic proxy that wraps your class and changes its implementation. I do not know what are you doing exactly, so I am not sure you can really use this method. But I hope you can. If not go back to #1 or #2.
yes it's possible ,but you should not do it, because it contradicts one of the SOLID principles. More exactly it contradicts Liskov substitution principle.
Note:
Let q(x) be a property provable about objects x of type T. Then q(y)
should be provable for objects y of type S, where S is a subtype of T.
So in other words , private method is property of object, so your object of inherited type must have the same property. The same with throws for methods.
Java restricts it because of it.