I wan't to make a method declaration in a superclass called 'dataItem' so that all subclasses that implement that method must have a return type that is of that implementing class. Is that possible?
For example if I have class 'Experiment' which implements 'dataItem' and I have method newItem() . Which for 'Experiment' should only be able to return 'Experiment' datatype and not any other implementation of 'dataItem'.
You can't force a class method to return the type it is a member of. You have to actually specify it.
public class DataItem {
public DataItem getItem() {return null;}
}
public class Experiment extends DataItem {
#Override
public Experiment getItem() {return null;}
}
This works because Experiment is a sub class of DataItem and can therefore be used anywhere a DataItem could be used.
I suppose you're looking for this:
public interface dataitem<T>
{
public T newItem();
};
public class Element implements dataitem<Element>
{
#Override
public Element newItem()
{
return new Element();
}
}
Related
public class TestClass {
private class Parent {
public Object returnSomething() {
return new Object();
}
}
private class Child extends Parent {
public String returnIt() {
return (String) super.returnSomething();
}
}
private class GrandChild extends Child {
public StringBuilder returnIt() {
return (StringBuilder) super.returnSomething();
}
}
}
My IDE complains about that the method in child clashing with the method in grandchild. The method definitions are different on the return type, so I don't see how they can be clashing.
Can someone help me to understand what Java is not allowing here?
In Java, method overriding is not possible with different return type unless it is covariant return types for overridden methods.
StringBuilder is not a sub class of String so compiler is not allowing to overide the method returnIt()
public final class StringBuilder extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
So, if you change return type of returnIt() in Child , it will work,
private class Child extends Parent {
public CharSequence returnIt() {
return (String) super.returnSomething();
}
}
Both methods have same name and input arguments, so the compiler qualifies them as same method, even though their return type differs.
Overriding method and changing only the return type is not acceptable by the compiler.
In order to return different type, you can :
use new method name, like (returnItAsStringBuilder)
add additional argument to your method
use generic types:
Example:
private class Child<T> extends Parent {
public T returnIt() {
return (T) super.returnSomething();
}
}
private class GrandChild extends Child<StringBuilder> {
}
But looking at this code, it will always fail. You will get ClassCastExcception, because in Parent class you are creating plain Object, which cannot be casted to anything else.
You should consider abstract parent class;
private abstract class Parent <T>{
public abstract T returnSomething();
}
private class GrandChild extends Parent<StringBuilder> {
#Override
public StringBuilder returnSomething() {
return new StringBuilder();
}
}
Item is an abstract class with subclasses Potion, Weapon. Shield.
The useItem() method is an abstract method defined in each of Item's subclasses
get_item return object of class Item
The getItem method returns an object of class subclass of Item
case "use":
if (hero.get_item() instanceof Potion) {
hero.<Potion>getItem(Potion.class).useItem();
} else if (hero.get_item() instanceof Weapon) {
hero.<Weapon>getItem(Weapon.class).useItem();
} else if (hero.get_item() instanceof Shield) {
hero.<Shield>getItem(Shield.class).useItem();
}
break;
is there a way I can condense this code into something like...
Class itemclass = hero.getItem().getClass();
hero.<itemclass>getItem(itemclass.class).useItem();
The code above does not compile but I am looking for something like it. I am trying to avoid if else statements because there are many more items.
Edit:
The reason i did not initially use hero.get_item().useItem() was because
i was trying to do
Weapon sword = hero.get_item();
so i could access methods such as sword.getDamage()
However, I would get the error error: incompatible types: Item cannot be converted to a Weapon
so that is why I created (help from #marsouf) hero.<Weapon>getItem(Weapon.class)
Today i created the method abstract public void useItem();
and since it is a method of the Item class I am able to use hero.getItem().useItem()
It would make more sense to haven an Interface for Item with the method useItem().
Then have an implementation for Potion, Shield etc.
This way you avoid having to cast and make it more complex than it is.
useItem() does not belong in the abstract class if its not giving any functionality, and less needed now Interfaces can have default methods.
My idea is to use the magic of generics without not cast
public class Character<T extends Item> {
private T item;
public Character (T item){
this.item = item;
}
public T getItem(){
return item;
}
}
When you create a hero:
Character hero = new Character<Weapon>(new Weapon("sword"));
after this you can use it like:
hero.getItem().useItem(); // abstract method from Item class
hero.getItem().getPower(); //where power is a Weapon method
Character class you can extend like:
public class Hero<T> extend Character<T>{
//add there your custom methods or override Character methods
}
Difficult to answer without seeing the contracts being involved (hero.get_item(), hero.getItem()).
But have you tried:
Class<?> itemClass = hero.get_item().getClass();
hero.getItem(itemClass).useIt();
?
Assuming you are set on using generics the way you're using them... here's how.
First, I've created some extremely simple classes to mimic your structure from this and your other question: a class which uses instances of a particular abstract class.
public class ACOne extends AbstractClass
{
#Override
public void use(){System.out.println("Used item ACOne!");}
}
public class ACTwo extends AbstractClass
{
#Override
public void use(){System.out.println("Used item ACTwo!");}
}
public abstract class AbstractClass
{
public abstract void use();
}
public class UserClass
{
private AbstractClass item;
public UserClass (AbstractClass item)
{
this.item = item;
}
public Class<? extends AbstractClass> getItemClass()
{
return item.getClass();
}
public <T extends AbstractClass> T getItem (Class <? extends T> targetType)
{
return targetType.cast(this.item);
}
public void setItem (AbstractClass item)
{
this.item = item;
}
}
public class CastingSubclasses
{
public void testCastingSubclasses()
{
UserClass user = new UserClass(new ACOne());
user.setItem(new ACTwo());
user.getItem(user.getItemClass()).use();
}
}
This program, when run, prints out "Used item ACTwo!"
The crux here is in the getItemClass method on the UserClass (your Character class).
Also, it's common to call these methods which get the Class object 'getClazz', since there is a default method 'getClass' that you don't want to override.
Here it made sense to just keep the spelling.
Is it possible in Java to use this inside a method of an abstract class, but as an instance of the subclass at hand, not just of the abstract class?
abstract class MyAbstractClass <MyImplementingClass extends MyAbstractClass> {
public abstract MyImplementingClass self();
}
which I overwrite in every subclass I with
class MyImplementingClass extends MyAbstractClass<MyImplementingClass> {
#Override public MyImplementingClass self() {
return this;
}
}
but I wonder if there are more elegant methods to do this. In particular, one that doesn't require every subclass to overwrite a routine like self().
The issue here I believe is that your self() method returns MyImplementingClass and not MyAbstractClass.
You should return a MyAbstractClass, the dynamic type of the returned object will be the relevant one.
I also do not follow why wouldn't you just use this? It returns the object itself, with the correct dynamic type, regardless of where it is called. You can cast it if you need to
When overriding methods in Java, you can override the return type to be a subclass of the original type. This code is completely valid:
abstract class MyAbstractClass {
public MyAbstractClass self() {
return this;
}
}
And the concrete class:
class MyImplementingClass extends MyAbstractClass {
#Override
public MyImplementingClass self() {
return this;
}
}
This is also why you can override clone() to return an exact type instead of just Object:
public class SomeCloneable implements Cloneable {
#Override
public SomeCloneable clone() {
return new SomeCloneable();
}
}
I believe, you can return newInstance() of a class to behave like that
#Override public MyImplementingClass self() {
return MyImplementingClass.newInstance();
}
It looks like this is impossible to do, but does anyone have a clever way around this problem?
public class SomeClassIterableWrapper<S, T extends SomeClass & S> implements Iterable<S>
Where S is supposed to be an interface of some unknown type and SomeClass is a 2D array with a row index, similar in functionality to a bidirectional JDBC resultset. Subclasses of SomeClass have custom getters and setters for each column. I want to be able to iterate through this structure like I would a List. I want to implement a common interface between my SomeClass and Bean to have access to the getters and setters. As such S needs to be that interface. However the declaration I provided does not work. Is there a way to work around this?
edit to show my desired implementation:
public class SomeClassIterableWrapper<S, T extends SomeClass & S> implements Iterable<S>{
T object;
public SomeClassWrapper(T object){
this.object = object;
}
#Override
public Iterator<S> iterator() {
object.setIndex(-1);
return new SomeClassIterator<S>();
}
private class SomeClassIterator<S> implements Iterator<S> {
#Override
public boolean hasNext() {
return object.index() < object.rowSize() - 1;
}
#Override
public S next() {
object.next();
//safe because only interface methods allowed, can't further manipulate index
return object;
}
#Override
public void remove() {
object.deleteRow();
}
}
Can't you parameterize SomeClass with S? Then you could have
public class SomeClassIterableWrapper<S, T extends SomeClass<S>>
implements Iterable<S>{
I think the S in extends SomeClass & S
public class SomeClassIterableWrapper
has to be a definite class because in this context,
S has to be a class that is extending something.
Is there a way you can narrow down what the
potential classes that are used in place of S are?
You could use multiple ampersands if you have multiple
classes that T should extend
I confess that I don't fully comprehend the problem but this is what I suggest:
Create an interface of S. It contains one method ad it returns the S object.
public interface SWrapper<S> {
S getS();
}
Then create an implementation:
public class SImpl implements SWrapper<SImpl> {
#Override
public SImpl getS() {
return this;
}
}
You can now create:
public class SomeClass<T extends SomeClass & SWrapper<T>> {
private final T object;
public SomeClass(T object) {
this.object = object;
}
}
You will have to modify your usage a bit but perhaps it works.
I got a problem with java when i try to override a method,my code is following:
public abstract class CustomAdapter{
public abstract Boolean addItem(Class<? extends Object> aObject);
}
public class RainAdapter extends CustomAdapter {
#Override
public Boolean addItem(ClassOfRain aRainInfo) {
// do something
return true;
}
}
Can I declare the the "Class" to "ClassOfRain"?
If yes,how to do?
Thanks for your reading!
I think you are a bit confused. Are you sure you are not trying to say:
public abstract class CustomAdapter<T extends Object> {
public abstract Boolean addItem(T aObject);
}
public class RainAdapter extends CustomAdapter<Rain> {
#Override
public Boolean addItem(Rain aRainInfo) {
// do something
return true;
}
}
In my interpretation of your class structure, you are trying to make a generic addItem method, so passing around the actual class object is of no use.
That is not possible. A method override means that you put exactly the same method header. Only thing you can change is the name of the given parameter.
Class<Rain.class> would hold the reflection of Rain class. But this will not work, because overridden methods must have the same formal parameters, so you'll have to use Class<? extends Object>.
the method signatures must match when implementing abstract/interface methods and/or overwriting ... you could do something like this tho
public abstract class CustomAdapter{
public abstract Boolean addItem( Object o );
}
public class RainAdapter extends CustomAdapter {
public Boolean addItem( Object o ){
if ( o.getClassName().equals( "ClassOfRain" ) ){
return this.addItem( (ClassOfRain) o );
}
return false;
}
private Boolean addItem(ClassOfRain aRainInfo) {
// do something
return true;
}
}