Comparable and compareto - java

I have a problem. I have a class that extends another class and implements Comparable. But when I tried to compile my program I had this error: Flight is not abstract and does not override abstract method compareTo. Anyway, the code of Flight is this:
class Flight extends KeyFlight implements Comparable<Flight>{
public KeyFlight kf;
public boolean departure;
public void Flight(){
KeyFlight kf=new KeyFlight();
boolean departure=false;
}
public int compareTo(KeyFlight other){
if (kf.time==other.time){
if (kf.key<other.key){
return kf.key;
} else {
return other.key;
}
} else {
if (kf.time <other.time){
return kf.key;
} else {
return other.key;
}
}
}
}
Thank you in advance!

You should use
implements Comparable<KeyFlight>
Instead of
implements Comparable<Flight>
As you want to compare two keyflights rather than flights itself. The Type of parameter that you defines in compareTo, should match with the type you specified in implements clause that you are going to compare with.
Another issue with your code is, in your constructor you are re-defining KeyFlight, it should be
public void Flight(){
kf=new KeyFlight();
Else you will get NullPointerException in future. Same applies for your departure boolean.
A side note, By Default in java boolean is initialised to false, so you don't have to explicitly say that in constructor.

I think the type of compareTo's argument is wrong, it should be
public int compareTo(Flight other){

The compareTo method in your class is not to a valid override because you define that your class implement Comparable<Flight> So in order to override this method in your class you need to change the variable type of other from KeyFlight to Flight.
#Override
public int compareTo(Flight o) {
//your logic here
}

Related

Avoid using multiple if-else statements

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.

Method declaration in superclass

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();
}
}

Overriding a method with different return types in java?

I have read a book and it says I can override a method if it has the same signature. according to the book the signature of a method is Method_Name + Parameters passed.
as per the book, i can override a method which has different return types. Is it actually possible to override a method with different return type in Java? because i have done a some search on the net i found people saying that to override a method the return type should be same as well.
according to the book it also says the java will throw a compile error when we try to overload a method with same method name and parameters but different return types since the signature means only the method name and parameters. If this is true, we should be able to override a method with different return type.
Please help me to understand this. Thanks in advance.
You can return a different type, as long as it's compatible with the return type of the overridden method. Compatible means: it's a subclass, sub-interface, or implementation of the class or interface returned by the overridden method.
And that's logical. If a method returns an Animal, and your derived class returns a Cow, you're not breaking the contract of the superclass method, since a Cow is an Animal. If the derived class returns a Banana, that isn't correct anymore, since a Banana is not an Animal.
Your parent class has made a promise to the outside world. For example, the method:
public Price calculatePrice(Items[] items).
It tells the world to expect a Price.
If you enhance that functionality in your subclass, you still have to keep your parent classes' original promises for it.
You can add overloaded ways of calculating:
public Price calculatePrice(Items[] items, Integer minimumCharge).
You can even improve your parent's promises by using a MORE specific return type:
public AccuratePrice calculatePrice(Items[] items, Integer minimumCharge).
But you must return at least the type that your parent promised.
The same goes for Exceptions in the method declaration too.
Yes, it is possible since Java 5, it is called covariant return type. The return type should be a subcass of super class method return type (primitive types are not allowed). Example
class X implements Cloneable {
#Override
protected X clone() {
try {
return (X) super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(e); // can never happen
}
}
}
Here is an example:
class Base {
public Number test() {
return 0;
}
}
class A extends Base {
public Long test() {
return 1L;
}
}
Your overriden method can have same type or the sub-type of the
original return type which is called as covariant return.
If you change the return type of the overriden method to something else which is not a sub-type of the original type, then you'd get a compile time error.
Yes we can override different return types but they should be subclass.
public class Shape {
public Shape area(Integer i) {
System.out.println("Sape Area");
System.out.println("Integer");
return null;
}
}
package com.oops;
public class Circle extends Shape {
public Circle area(Integer i) {
System.out.println("Circle Area");
System.out.println("int");
return null;
}
}
// Covariant Overriding
public class Parent {
public Parent(){}
String parentName;
public Parent(String parentName){
this.parentName=parentName;
System.out.println(this.parentName);
}
public Parent show(){
return new Parent("Parent");
}
}
public class Child extends Parent{
public Child(){}
String name;
public Child(String name){
this.name=name;
System.out.println(this.name);
}
public Child show(){
return new Child("Child");
}
}
public class Main {
public static void main(String[] args) {
Parent parent=new Child();
parent.show();
Parent parent1=new Parent();
parent1.show();
}
}

Java Method override with the parameter "Class<? extends Object>"

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;
}
}

Cannot implement Queue - does not override abstract method offer(java.lang.Object)

I am trying to implement the Java 1.6 Queue interface, but I am getting the error:
MyBoundedQueue.java:27: MyBoundedQueue is not abstract and does not override abstract method offer(java.lang.Object) in java.util.Queue
What I really don't understand is that there is no offer(Object) method in the Queue class. The Java 1.6 API for Queue says there is a method boolean offer(E e), where E is a parameterized type, and indeed, I have implemented that, as shown below.
Any help?
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Queue;
public class MyBoundedQueue<ItemType> implements Queue
{
private int _maxSize;
private ArrayDeque<ItemType> _window;
public MyBoundedQueue(int maxSize)
{
_maxSize = maxSize;
_window = new ArrayDeque<ItemType>(_maxSize);
}
public boolean add(ItemType item)
{
if (_window.size() >= _maxSize)
{
_window.removeFirst();
}
_window.addLast(item);
}
public ItemType element()
{
return _window.element();
}
public boolean offer(ItemType item)
{
add(item);
return true;
}
public ItemType peek()
{
return _window.peek();
}
public ItemType poll()
{
return _window.poll();
}
public ItemType remove()
{
return _window.remove();
}
public void clear()
{
_window.clear();
}
public int size()
{
return _window.size();
}
public Iterator<ItemType> iterator()
{
return _window.iterator();
}
}
You need to change it to:
public class MyBoundedQueue implements Queue<ItemType>
It's telling you offer(Object) because without the Generic typing that's what it would be. You also don't need to specify a generic type for your class ... you're not using generic types anywhere.
If you wanted your class to use generics you'd want to do:
public class MyBoundedQueue<T> implements Queue<T> {
...
And everywhere you currently have ItemType you'd use T instead.
Please stick to coding conventions and use a single, upper-case letter for type parameters!
You'll need to implement Queue<T> (or Queue<ItemType> if you insist)
Is ItemType a fixed class, or is it supposed to be a parameter?
If it's fixed, it should be class MyBoundedDeque implements Queue<ItemType>, not the other way around.
Otherwise, it should be class MyBoundedQueue<ItemType> implements Queue<ItemType>.
Change to
MyBoundedQueue implements Queue<ItemType>
Your code is equivalent to
MyBoundedQueue implements Queue<Object>

Categories