Java Overriding abstract class method with an interface as param - java

I have this abstract class:
public abstract class Foo{
//some attributes
public Foo(params){}
public abstract SomeInterface search(Long id);
public abstract boolean insert(SomeInterface param);
}
I have the following class:
public class InterfaceImplementation implements SomeInterface {
//Some code here
}
Then I create an instance of Foo:
public class Bar extends Foo{
public Foo(params){
super(params);
}
#Override
public InterfaceImplementation search(Long id){
// some code here
}
// The above code compiles
#Override
public boolean insert(InterfaceImplementation param){
// some code specific to the InterfaceImplementation here
}
// This function does not compile/
}
So, what am I doing wrong and how can I achieve what I'm trying to do?

Your class Bar doesn't override insert, because the parameter types must match exactly. This is because your implementation takes an InterfaceImplementation, not a SomeInterface.
What you can do to get this to compile:
Take a SomeInterface as a parameter in Bar's insert method, because any subclass should be able to process any implementation of SomeInterface, as specified by Foo.
OR
Introduce generics in SomeInterface to specify what should be the parameter type.
public abstract class Foo<T extends SomeInterface>{
and
public abstract boolean insert(T param);
Then you can specify what T is in the subclass:
public class Bar extends Foo<InterfaceImplementation>{
and
#Override
public boolean insert(InterfaceImplementation param){

Let's say I had
Foo foo = new Bar();
and tried to do
foo.insert(new OtherInterfaceImpl());
I would be allowed to do this because Foo#insert accepts a SomeInterface and OtherInterfaceImpl implements SomeInterface.
However, Bar's implementation of insert could not accept a OtherInterfaceImpl since you specifically said so with this declaration
public boolean insert(InterfaceImplementation param){
This would break type safety and is therefore not allowed.
You can use generics as rgettman has shown.

You cannot restrict parameters when implememting an superclass method.
You can restrict the output to subtypes.
Consider the method
Number sum(Number a, Number b);
which may be used with arbitrary numbers, e.g.
Number out = sum(Double.valueOf(1.23), Integer.valueOf(7));
and the "candidates"
Double sum(Number a, Number b) {
return a.doubleValue() + b.doubleValue()
}
vs.
Number sum(Integer a, Double b) {
return (Byte) (a.doubleValue() + b.doubleValue());
}
Which of the two implements above API correctly?

Related

Bounded type parameters: cannot access subtype methods when overriding

I'm new to using bounded types in Java, and I'm not sure if the following is a programming error because of a bad use of inheritance or a javac bug
I need to define two different type of objects: things which have to be managed and managers of that things. That's why I created an abstract class to model the common behavior of those things
public abstract class AbstractThing {
// Common method implemented
public void hello() {
System.out.println("HI, I'm AbstractThing");
}
}
and an interface to define the methods that those things' manager must implement
public interface AbstractManager {
// Operation that a things' manager must implement
public <T extends AbstractThing> void greet(T t);
}
So suppose I create two concrete things classes, one of them just inherits the abstract one:
public class Thing extends AbstractThing {
// Constructor
public Thing() {}
}
but the other one implements an own method:
public class AnotherThing extends AbstractThing {
// Constructor
public AnotherThing() {}
// Extra method which this class implements
public void goodbye() {
System.out.println("BYE, I'm AnotherThing");
}
}
But when I define a manager as follows:
public class Manager implements AbstractManager {
// Constructor method
public Manager() {}
// Implementation of the interface's method fails
#Override
public <AnotherThing extends AbstractThing>
void greet(AnotherThing t) {
// I can use this method, which AnotherThing inherits from AbstractThing
t.hello();
// But I can't use this one defined by AnotherThing
t.goodbye();
}
}
I get the error:
AnotherManager.java:15: error: cannot find symbol
t.goodbye();
^
symbol: method goodbye()
location: variable t of type AnotherThing
where AnotherThing is a type-variable:
AnotherThing extends AbstractThing declared in method <AnotherThing>greet(AnotherThing)
1 error
And I don't understand why, because it's recognizing the class as AnotherThing, but it's dealing it as AbstractThing. I've tried to cast the object as the subclass, but it doesn't work
I've also checked that it only happens when I try to access the subtype methods, because the following manager compile and works perfectly:
public class Manager implements AbstractManager {
// Constructor method
public Manager() {}
// Implementation of the method defined into the interface
#Override
public <Thing extends AbstractThing>
void greet(Thing t) {
t.hello();
}
// I can overload the method "greet" without overriding the interface
// and it works for AnotherThing
public void greet(AnotherThing t) {
t.hello();
t.goodbye();
}
}
Any idea about what's happening there?
Here's why
It's not difficult to figure out if you do something like this
public class Manager implements AbstractManager {
// Constructor method
public Manager() {}
// Implementation of the interface's method fails
#Override
public <T extends AbstractThing>
void greet(T t) {
// I can use this method, which T inherits from AbstractThing
t.hello();
// But I can't use this one because T inherits from AbstractThing which does not know this method
t.goodbye();
}
}
In other words, the word before the "extends" is not supposed to be a class name, but a generic identifier (a variable name).
In this case, since T (or wharever you call it) is AbstractThing, it does not know what goodbye() is.
Now, why your last example works?
Because you're saying that greet receives a object of type AnotherThing, not a generic type such as T.
AnotherThing in <AnotherThing extends AbstractThing> has nothing to do with the class AnotherThing. It's the name a type parameter, same as if it were called T. The reason it acts like AbstractThing is because that's all we know it is. Your method doesn't know how it's parameterized; all it knows is that it's getting a subclass of AbstractThing. This can be useful for constructs where we need to capture the type, but we don't care what subtype it is, e.g.:
<T extends AbstractThing> void copy(List<T> from, List<T> to) {
for (T t : from) {
t.hello();
to.add(t);
}
}
But if you want a specialized subclass of AbstractManager to manage AnotherThing, the type parameter should be on the class, not the method:
public interface AbstractManager<T extends AbstractThing> {
// Operation that a things' manager must implement
public void greet(T t);
}
public class AnotherManager implements AbstractManager<AnotherThing> {
#Override
public void greet(AnotherThing t) {
t.hello();
t.goodbye();
}
}

How to refer the generic type of super class in subclass in Java?

I have following base class
class Base<T> {
// ...
}
and I have this class to extend the Base
class Derived extends Base<String> {
public void doSomething(String param) { // this works
}
public void doSomething(Base::T param) { // this DOES NOT work
}
}
I want know whether there is a java trick to get the second function definition to work without using the concrete class String directly?
Yes I have a reason. There are many classes need extend the Base with different concrete type. I want to avoid change the funciton signature in each class, this should be avoided if possible.
If you have many classes that need to extend the Base<T> class and they all have a doSomething method, you should probably put the doSomething in Base<T>:
class Base<T> {
public void doSomething(T param) {} // or even make this abstract
}
And then, IDEs like IntelliJ IDEA can generate the overridden method for you. When you start typing the method name, this pops up:
You press enter, and then it will be generated for you.
#Override
public void doSomething(String param) {
super.doSomething(param);
}
I suspect that you might be copy and pasting the implementation of doSomething, because otherwise why you think it is annoying to change the parameter type for each implementation?
If the implementations are mostly the same, consider having the doSomething method in the Base<T>, then extract the parts that are different into a doSomethingImpl method which will be overridden by the derived classes.
In order to pass different parameters to your method, you can implement an upper bounded type parameter.
class Derived<T extends Foo> extends Base<Foo> {
public void doSomething(Foo param) { // this works
}
}
public <T extends Foo> void doSomething(List<T> foos) {}
public void doSomething(List<Foo> foo) {}
Given: class Bar extends Foo { }
List<Bar> list = new ArrayList<Bar>();
doSomething(list);

How to satisfy parameter type Class<? extends someInterface> in java

Consider the following code
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
public interface myInterface {
int doSomething();
}
public class myInterfaceImpl implements myInterface {
public int doSomething() {
return 1;
}
}
public void callDoSomething(Class<? extends myInterface> myVar) {
System.out.println(myVar.doSomething());
}
On this line callDoSomething(new myInterfaceImpl()); I get the following error.
Error:(32, 25) java: incompatible types: com.myProject.myTest.myInterfaceImpl
cannot be converted to java.lang.Class<? extends com.myProject.myTest.myInterface>
How do I satisfy the parameter type? If only an interface is provided to me.
I want to bound the class that has an interface, but it seems like this is not avaiable to me
Class<? implements myInterace>
Edit:
The reason I want to do this is because I want to provide a custom kafka partitioner.
public Builder<K, V> withCustomPartitionner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
It looks like you want to be able to call methods on the parameter that's given. In that case, you'll want the actual instance of your interface, not the Class associated with it.
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
Class<> is used when you want to use reflection to do something with the specific class type that you're interested in:
public void outputClassInfo(Class<? extends myInterface> myClass) {
System.out.println(myClass.getName());
}
If that's what you're going for, you'll want to provide the class at compile time like this:
outputClassInfo(myInterfaceImpl.class);
Or, if you won't know which class you're dealing with until runtime, you can use reflection:
myInterface thing = getThing();
outputClassInfo(thing.getClass());
So, in the example you're providing in your edit, I'm guessing you want:
public Builder<K, V> withCustomPartitioner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
// Usage
builder
.withCustomPartitioner(FooPartitioner.class)
...
This type Class<? extends myInterface> myVar corresponds to a Class instance not to an instance of myInterface.
You generally don't pass a class as parameter (but for reflection purposes or to bypass generics erasures). So what you need as parameter is probably :
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
That you could invoke :
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
The parameter to callDoSomething shouldn't be a class. It must be an instance of that class or it's subclass.
public <T extends myInterface> void callDoSomething(T myVar) {
System.out.println(myVar.doSomething());
}
On a side note, don't name Java classes/interfaces starting with lower case.
As rightly mentioned by Andy Turner#, there is no need to use a type parameter here and you can just refer to the type as myInterface
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
You need to pass the Class not an instance.
callDoSomething(MyInterfaceImpl.class);

Apply generically enum member or method

I have an interface ServiceArgument which defines a size() promise.
public interface ServiceArgument {
public int size ();
}
Some of my enum types implement this interface
public enum StringCode implements ServiceArgument {
FOO,
BAR,
BACON,
public int size() {
return values().length;
}
}
Some of my class follow a EnumService abstract class.
public abstract class EnumService {
abstract void query (Enum<? extends ServiceArgument> e);
}
And to wrap it up, some class extends this abstract class :
public class ServiceTranslation extends EnumService implements Serializable {
/**some code and ctors and transient stuff etc **/
#Override
void query (Enum<? extends ServiceArgument> e) {
//line that matters :
if (e.ordinal() >= e.size()) {
throw InvalidStringCodeAsked();
}
}
My problem is, I can't use e.size() at the last line, because I wouldn't use FOO.size() in my example enumeration.
Is there a way to, either :
1) specialise what the query method accepts as a parameter in the concrete implementations of EnumService
2) get the concrete type of the Enum called in ServiceTranslation.query(MYSTERIOUS.ENUM), in order to be able to call ConcreteENUM.size(). or even ConcreteEnum.values().length, it's the same.
3) even filter everything that is not from the right enumerated type to throw directly a InvalidEnumeratedTypeException through method override, but i'm not familiar with multiple overriding.
4) something I didn't think of
Edit : #shmosel in the comment is right, even if I get the wrong enumeration as argument, it will never be greater than its size. No point in comparing it to its size.
How about this one?
public abstract class EnumService {
abstract <T extends Enum<T> & ServiceArgument> void query (T e);
}
public class ServiceTranslation extends EnumService implements Serializable {
#Override
<T extends Enum<T> & ServiceArgument> void query (T e) {
if (e.ordinal() >= e.size()) {
throw InvalidStringCodeAsked();
}
}
}

Java - enum wildcard

I have some problems implementing a Java feature.
I have a list of Sensors. I have different kinds of them, they all extend the base class Sensor.
I have some abstract functions in the base class, and I want these functions to take an Enum as a parameter. The problem is that the Enum is unique for each sub class, and therefore, I can't declare the Enum in the base class.
The code below has Enum as parameter. I know it's not legal syntax, but I just want to illustrate that this is where I want to have the sub class Enum as parameter.
private Vector<Sensor> sensors;
public abstract class Sensor {
public Sensor() {}
public abstract int getParam(Enum param);
public abstract void setParam(Enum param, int value);
}
public class TempSensor extends Sensor {
// Parameter names
public static enum TEMP_PARAMETERS{ PARAM_ALARM_HI, PARAM_ALARM_LO }
public TempSensor() {}
#Override
public int getParam(TEMP_PARAMETERS param) {
// Will do some stuff here
return 0;
}
#Override
public void setParam(TEMP_PARAMETERS param, int value) {
// Will do some stuff here
}
}
If the different Enums implement an interface, I can use the interface as the parameter type in the abstract methods, but then I can pass Enums that don't belong to the respective class as parameter. Is there a way to avoid that?
Looks like you want contradictory things. The whole point of using polymorphism is to take advantage of the substitution principle.
If you want to have a class hierarchy and be sure the right type is entered to the right object, you may consider using the factory pattern.
I strongly recommend against inheritance on Enums; Java doesn't handle that well.
You're on the right track. Assuming you have a marker interface called MyEnumTypeInterface, just have your different enums implement that inferface. Then use MyEnumTypeInterface as the type of the formal parameter for your methods that accept the enum. However, you need to ensure that you're getting an enum that implements MyEnumTypeInterface and not just any other class that implements MyEnumTypeInterface:
public <E extends Enum<E> & MyEnumTypeInterface>void getParam(E e)
This ensures that the formal parameter is an enum and that it implements MyEnumTypeInterface; the methed won't accept as a parameter, another class that also implements MyEnumTypeInterface.
So your classes end up looking like this:
public interface MyEnumTypeInterface {
}
public abstract class Sensor {
public Sensor() {}
public abstract <E extends Enum<E> & MyEnumTypeInterface>int getParam(E param);
public abstract <E extends Enum<E> & MyEnumTypeInterface>void setParam(E param, int value);
}
public enum TempEnum extends MyEnumTypeInterface {
PARAM_ALARM_HI,
PARAM_ALARM_LO
}
public class TempSensor extends Sensor {
public TempSensor() {}
#Override
public<E extends Enum<E> & MyEnumTypeInterface>int getParam(E param) {
return 0;
}
#Override
public <E extends Enum<E> & MyEnumTypeInterface>void setParam(E param, int value) {
// Will do some stuff here
}
}
So you want each Sensor to work a particular param type? That would mean making Sensor generic.
public abstract class Sensor<P extend Enum<P>> {
public Sensor() {}
public abstract int getParam(P param);
public abstract void setParam(P param, int value);
}
There are probably bigger problems with you design. Fixing those could remove the requirement for the get and set.

Categories

Resources