Say I'm making a class that implements an interface, and have code like this:
public void setGoalLocation(Location loc)
{
goal = loc;
}
The code doesn't compile, because it demands that I implement a "setGoalLocation(Ilocation loc)" method, where "Ilocation" is an interface and "Location" is an actual concrete class that implements it.
This means that I have to do something like this:
public void setGoalLocation(ILocation loc)
{
goal = (Location)loc;
}
That just seems really awkward. And funnily enough, Java doesn't seem to care about other methods returning Location instead of the interface ILocation. This works:
public Location getStartLocation()
{
return start;
}
...even though the "required" method would be a "public ILocation getStartLocation". Can anyone explain why this is, and any help for making the code less awkward? I'd like to be able to use a Location as a parameter, not an ILocation.
The problem is that the interface requires a method that accepts anything as an argument that is a subtype of ILocation, not just an object of the specific type Location. If you had another concrete type Position that was a subtype of ILocation, then implementing the interface would require you to accept a Position object as well as a Location object.
Note that in your work-around using a cast, you'd get a ClassCastException at run time if you happened to pass a Position instead of a Location object.
As a design issue, to get around this you could define your interface as a generic:
interface <T extends ILocation> TheInterface {
void setGoalLocation(T loc);
}
Then your concrete class can bound the generic parameter:
public class MyClass implements TheInterface<Location> {
public void setGoalLocation(Location loc) {
. . .
}
}
As to return types, that works because any Location object is an ILocation, so when you return a Location you are returning an ILocation.
Java supports covariant return types where the return type of a method in a subclass (or interface implementation) can return a subclass (or implementation) of the declared type. So in general, the following is allowed
public class A {}
public class B extends A {}
public class C {
A getSomething();
}
public class D extends C {
B getSomething();
}
If the interface has a method that takes an interface type, you cannot override it with a different signature.
public interface I {
void setSomething(ISomething somethingInterface);
}
You cannot do
public class Something implements ISomething {}
public class MyI implements I {
void setSomething(Something somethingInterface);
}
Related
I am trying to make a method which takes in a variable object type as a parameter, and then updates a database depending on what object was passed, a bit like how Petapoco works for C#. For this I am trying to use a generic method in which the object that is passed passes a number of checks before it is inserted/updated into its relevant table. A number of questions on Stack Overflow point me towards using a method signature like this:
public <T> void upsertObject(Class<T> objectClass, T actualObject) { }
Within the method I would like to be able to call methods like actualObject.getId() but the compiler needs to know the actual type of the object to call its relevant methods. Is there any way around this? How would I go about achieving these calls?
EDIT:
Edited for more clarity
After adding an interface with which to bind T, I found I was getting the error:
"Cannot make a static reference to the non-static method getId() from the type CycleComponent"
The method now looks like this, the error line is under T.getId()
public <T extends CycleComponent> void upsertObject(Class<T> objectClass, T fitProObject) {
if (objectClass.getName() == "Cycle") {
if (isInserted(T.getId(), "Cycles")) {
// update the database
}else {
// insert into the database
}
}
}
The interface looks like:
public interface CycleComponent {
String getId();
}
And the method in the Cycle class looks like:
public String getId() {
return this.cycleId;
}
You can do it with generic type bounds.
Define:
public <T extends SomeType> void upsertObject(Class<T> objectClass, T actualObject) { }
Where SomeType is a class or interface, and you'll be able to call methods of SomeType on the actualObject instance.
This would limit this method to being used only with types that extend SomeType (if it's a class) or implement SomeType (if it's an interface).
For example:
public interface SomeType {
String getId();
}
And:
public <T extends SomeType> void upsertObject(Class<T> objectClass, T actualObject) {
if (actualObject.getId() != null) {
...
}
}
Assuming this doesn't have to be absolutely generic (for example, it probably doesn't make sense to upsert a java.lang.Integer, right?), I'd define an interface with all the methods you need, and add that to the generic classification:
public interface Upsertable {
int getID();
// Other methods you may need...
}
public <T extends Upsertable> void upsertObject(Class<T> objectClass, T actualObject) { }
Is there any way in Java to enforce a subclass or interface implementation to have a constructor with a given signature?
Let's say that I´ve got either:
public interface MyInterface {
// any methods
}
or
public abstract class MyBaseClass {
// any abstract methods
}
Now, is it possible to do anything to require
public class MySubClass extends MyBaseClass {
public MySubClass(String s) { }
}
or
public class MySubClass implements MyInterface {
public MySubClass(String s) { }
}
to always have a constructor that takes a String as it´s only input parameter?
The obvious workaround is to create a factory interface with a method taking a String and inject it where required. Which is not what I would like to do.
Not really, the closest I think you can get is something like:
abstract class B {
public B(String s) {
}
}
public class A extends B {
public A(String s) {
super(s);
}
}
This forces A to implement a non default constructor which must call super(String) but can not prevent the following:
public class A extends B {
public A() {
super("");
}
}
There have been many times where I wished something like this existed, but sadly it doesn't. Even something like what David Soroko suggested wouldn't work because a subclass still wouldn't be forced to have a String constructor - it can just pass any String it likes to super. Simply put, there is no such thing within the Java syntax itself.
I suppose the closest one could get to such a capability is if someone built an annotation processor that allows you to use an annotation like #MustHaveUnaryConstructor(String.class) and then if any subclass does not have such a constructor, it causes compilation to fail and tells you which subclass broke the contract. But I haven't found such a thing and I don't know enough about annotation processing to build one myself. So TL;DR, no, you can't.
I'm trying to understand how to use generics in the form of a bounded type parameter in an interface. In this case, to avoid casting when using the bounded param in concrete implementations but I'm running into an issue. I will use the following example to illustrate my problem:
There's an interface and two concrete implementations
public abstract class Publication {
}
public class Newspaper extends Publication {
}
public class Newspaper extends Publication {
}
Then we have an interface representing a publishing house with two concrete implementations, one publishes magazine and the other newspapers
public interface Publisher {
public <T extends Publication >void publish(T publication);
}
Here are the two implementations
//DOES NOT COMPILE
public class MagazinePublisher implements Publisher{
#Override
public void publish(Magazine publication) {
//do something with the magazine, its already the type we need without casting
}
}
//COMPILES but a cast is required to get the type I want
public class NewsPaperPublisher implements Publisher{
#Override
public void publish(Publication publication) {
// Now I need to cast
Newspaper newspaper = (Newspaper)publication;
//Do some stuff here
}
}
The example maybe a bit contrived... I understand why the MagazinePublisher class doesn't compile: I'm trying to implement the method with a more specific class than defined by the contract of the publish method in the interface. So how do I user generics to avoid the cast in the NewsPaperPublisher class's publish() method?
You want to make the interface generic.
public interface Publisher <T extends Publication> {
void publish(T publication);
}
Then, instead of NewspaperPublisher and MagazinePublisher, you can just write Publisher<Newspaper> and Publisher<Magazine>.
Or if you want to provide different implementations depending on the type, you can write things like
public class NewspaperPublisher implements Publisher<Newspaper> {
#Override
public void publish(Newspaper publication) {
// do some stuff
}
}
I have an abstract class that has a generic method and I want to override the generic method by substituting specific types for the generic parameter. So in pseudo-code I have the following:
public abstract class GetAndParse {
public SomeClass var;
public abstract <T extends AnotherClass> void getAndParse(T... args);
}
public class Implementor extends GetAndParse {
// some field declarations
// some method declarations
#Override
public <SpecificClass> void getAndParse(SpecificClass... args) {
// method body making use of args
}
}
But for some reason I'm not allowed to do this? Am I making some kind of syntax error or is this kind of inheritance and overriding not allowed? Specifically I'm getting an error about #Override because the eclipse IDE keeps reminding me to implement getAndParse.
Here's how I want the above code to work. Somewhere else in my code there is a method that expects instances of objects that implement GetAndParse which specifically means that they have a getAndParse method that I can use. When I call getAndParse on that instance the compiler checks to see whether I have used specific instances of T in the proper way, so in particular T should extend AnotherClass and it should be SpecificClass.
What we are having here is two different methods with individual type parameters each.
public abstract <T extends AnotherClass> void getAndParse(Args... args);
This is a method with a type parameter named T, and bounded by AnotherClass, meaning each subtype of AnotherClass is allowed as a type parameter.
public <SpecificClass> void getAndParse(Args... args)
This is a method with a type parameter named SpecificClass, bounded by Object (meaning each type is allowed as a type parameter). Do you really want this?
Is the type parameter used inside Args? I think the problem would be there.
The meaning of
public abstract <T extends AnotherClass> void getAndParse(T... args);
is that the caller of the method can decide with which type parameter he wants to call the method, as long as this is some subtype of AnotherClass. This means that in effect the method can be called with any objects of type AnotherClass.
Since the caller can decide the type parameter, you can't in a subclass narrow down the parameter type to SpecificClass - this would not be an implementation of the method, but another method with same name (overloading).
Maybe you want something like this:
public abstract class GetAndParse<T extends AnotherClass> {
public SomeClass var;
public abstract void getAndParse(T... args);
}
public class Implementor extends GetAndParse<SpecificClass> {
// some field declarations
// some method declarations
#Override
public void getAndParse(SpecificClass... args) {
// method body making use of args
}
}
Now the getAndParse method implements the parent class' method.
You are seeing this problem because of the concept called "Erasure" in Java Generics.
Java uses "erasure" to support backward compatibility. i.e Java code which did not use generics.
Erasure Procedure:
The compiler will first do a type checking and then it will remove(erase) all the type parameters as much as possible, and also insert TypeCasting where ever necessary.
example:
public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);
will become
public abstract void getAndParse(AnotherClass paramAnotherClass);
In class "Implementor.java",
The code
public <SpecificClass> void getAndParse(T paramAnotherClass)
will become
public void getAndParse(SpecificClass paramAnotherClass){ }
the compiler will see that you have not implemented the abstract method correctly.
There is a type mismatch between the abstract method and the implemented method. This is why you are seeing the error.
More details can be found here.
http://today.java.net/pub/a/today/2003/12/02/explorations.html
You cannot override to specific type T because there is in fact (at the bytecode level if you wish) only one method getAndParse because of type erasure (see other answer):
public abstract void getAndParse(AnotherClass... args); // (1)
For every type of T, the same method is used.
You can overload it (I think):
public void getAndParse(SpecificClass... args); // (2)
but this will not a different method from (1) ant it will not be called by generic code:
T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass
No, it's not valid. What would happen if someone with a GetAndParse reference called it with a different class extending AnotherClass?
That becomes a nonsense when someone has a reference to type GetAndParse and tries to call the getAndParse method. If Cat and Dog extend AnotherClass. I should expect to be able to call GetAndParse#getAndParse with either a Cat or a Dog. But the implementation has tried to restrict it and make it less compatible!
Static method can't override
class Vehicle{
static void park(int location){
System.out.println("Vehicle parking..");
}}
class Car extends Vehicle{
#Override //error
void park(int location) { //error
System.out.println("Car Parking..");
}}
Private method can't override
class Vehicle{
private void park(int location){
System.out.println("Vehicle parking..");
}
void callPark(){
park(100);
}}
class Car extends Vehicle{
//#Override
void park(int location) {
System.out.println("Car Parking..");
}}
class Demo {
public static void main(String[] args) {
Vehicle v1=new Car();
v1.callPark();
}}
Final method can't override
class Vehicle{
final void park(int location){
System.out.println("Vehicle parking..");
}}
class Car extends Vehicle{
//#Override
void park(int location) { //error
System.out.println("Car Parking..");
}}
If I have a base class such that
public abstract class XMLSubscription <T extends XMLMessage>
Is it possible to write a method in XMLSubscription that returns a class object of T?
The only possible solution that I came up with is to have each descendant of XMLSubscription have a method like:
public class XMLStatusSubscription extends XMLSubscription<XMLStatusMessage>
{
public Class <XMLStatusMessage> getExpectedMessageType()
{
return XMLStatusMessage.class;
}
}
Unfortunately - and yes, this is due to type erasure - there is no way to return the Class object without providing it at runtime somehow.
Fortunately this is not usually too difficult. Here's how I've typically done this / seen it done:
public abstract class XMLSubscription <T extends XMLMessage> {
private Class<T> messageType;
protected XMLSubscription(Class<T> messageType) {
this.messageType = messageType;
}
public Class<T> getExpectedMessageType() {
return this.messageType;
}
}
public class XMLStatusSubscription extends XMLSubscription<XMLStatusMessage> {
public XMLStatusSubscription() {
super(XMLStatusMessage.class);
}
}
As you guessed, T is erased by the compiler. When you instantiate the object it has no idea that's it's supposed to deal with XMLStatusMessage objects. Your base class would define the following template method, and 1.5's covariant return types would keep the compiler happy with the concrete subclasses:
public Class<T> getExpectedMessageType()
There is one meta-comment: this looks a lot like procedural code, where something calls getExpectedMessageType() and then takes action based on the return type. This might be better implemented using a Visitor pattern, with the visitor implementing "doSomething" methods for each of the subclasses of XMLMessage.