Restriction of type parameter in method - java

Given 3 classes:
class Fruit implements Comparable<Fruit> {
private final int weigth;
public Fruit(int weight) {
this.weigth = weight;
}
#Override
public int compareTo(Fruit other) {
return Integer.compare(this.weigth, other.weigth);
}
public int getWeigth() {
return this.weigth;
}
}
class Apple extends Fruit {
public Apple(int weight) {
super(weight);
}
}
class Orange extends Fruit {
public Orange(int weight) {
super(weight);
}
}
I need to fix a code adjusting compareTo method to not allow comparing different Types of Fruit.
I understand that currently Apple and Orange have superclass Fruit which can hold a reference value to both subclasses. I cannot figure out how to correctly implement generics to fix the problem.
The compareTo method should show a compile-time error if the argument does not match the object which invokes the method.

Try this:
public abstract class Fruit<F extends Fruit<F>> implements Comparable<F> {
public int compareTo(F other) {
...
}
}
public final class Apple extends Fruit<Apple> {
// not needed to actually write the compareTo method, it'll just work.
}

Related

How call subclass method by superclass object

I have 2 subclass extended from the same superclass, and 3 objects will be created and store into an array of the superclass. I am wondering how can I call a subclass method by a superclass object, I try to convert the data type from Ship to CruiseShip or CargoShip but it does not work. If anyone can help I will be appreciated that.
Here is the superclass:
public class Ship {
private String name;
private String year;
public Ship() {}
public Ship(String n,String y) {...}
public void setName() {...}
public void setYear() {...}
public void getName() {...}
public void getYear() {...}
}
These two subclass basically are there same.
public class CruiseShip extends Ship {
private int passenger;
public CruiseShip() {}
public CruiseShip() {...}
public void setPassenager() {...}
public int getPassenager() {...}
public Strting showInfo() {this.getName()...etc}
}
public class CargoShip extends Ship {
private int capacity;
public CargoShip() {}
public CargoShip() {...}
public void setCapacity() {...}
public int getCapacity() {...}
public Strting showInfo() {this.getName()...etc}
}
Here is the main method:
public class report {
public static void main(String[] args) {
Ship[] shipList new Ship[3];
for (int i=0;i<3;i++) {//using for loop to create 3 objects randomly and pass into array}
for (int i=0;i<3;i++) {
if (shipList[i] instanceof CruiseShip) {
((CruiseShip)shipList[i]).showInfo(); //This way is not work.
}
else {
((CargoShip)shipList[i]).showInfo(); //This way is not work.
}
Take a look at Polymorphisms and Late Bindig. Basically late binding says that the appropriate method to be executed is determined at runtime based on the actual type of the object. So
class Ship {
public String showInfo() {return "I'm a ship";}
}
class CruiseShip extends Ship {
public String showInfo() {return "I'm a cruiseShip";}
}
class CargoShip extends Ship {
public String showInfo() {return "I'm a cargoShip";}
}
class Main {
public static void main(String argv[]) {
Ship[] ships = new Ship[]{new Ship(), new CargoShip(), new CruiseShip()};
for (Ship ship: ships) {
System.out.println(ship.showInfo());
// I'm a ship
// I'm a cargoShip
// I'm a cruiseShip
}
}
}
I'm not sure about the question you are trying to ask,
but this may answer the question you did ask.
public abstract class Ship
{
public final boolean hoot()
{
return implementHoot();
}
protected abstract boolean implementHoot();
}
public class BlamShip
extends Ship
{
protected boolean implementHoot()
{
return true;
}
}
Subclass methods (overrides) are automatically called even if the reference is of type super-class. You don't have to do anything.

I don't understand why my generic type declaration doesn't match

Here are the classes declarations:
public interface IPoint<N extends Number> {
...
}
public abstract class PointP<N extends Number> implements IPoint<N> {
...
}
public class Pointf extends PointP<Float> {
...
}
public interface ISegment<T extends Number, P extends IPoint<T>> {
...
}
public abstract class SegmentP<N extends Number, P extends IPoint<N>> implements ISegment<N, P> {
...
}
public class Segmentf extends SegmentP<Float, Pointf> {
...
}
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, IPoint<N>>> implements Iterable<S>, Iterator<S> {
...
}
public class LinesfIterator extends LinesPIterator<Float, Segmentf> {
...
}
The compiler refuses the Segmentf type in the generic declaration of the LinesfIterator class with the error message:
Bound mismatch: The type Segmentf is not a valid substitute for the bounded parameter <S extends ISegment<N,IPoint<N>>> of the type LinesPIterator<N,S>
However for me everything seems correct. The declaration of the LinesfIterator class seems to me to have the same hierarchical schema as the Segmentf class which compiles without problem.
Is there a solution to this way of doing things?
As already said, your hierarchy seems to be unnecessarily complex and shall be simplified. For example, I see no meaning in Pointf -> PointP -> IPoint the hierarchy.
If you want to fix your issue, you have to allow a subtype ? extends IPoint<N> in the LinesPIterator class, so:
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, ? extends IPoint<N>>>
implements Iterable<S>, Iterator<S>
{
// ...
}
Moreover, there would be better to implement only Iterable as long as it provides an Iterator and you might end up with duplicated implementation.
public static class LinesfIterator extends LinesPIterator<Segmentf, Pointf, Float> {
#Override
public Iterator<Segmentf> iterator() {
return new Iterator<Segmentf>() {
#Override
public boolean hasNext() { /* TO DO */ }
#Override
public Segmentf next() { /* TO DO */ }
};
}
}
This remark on the use of an anonymous class rather than a direct use really caught my attention because intuitively, when I can avoid going through an anonymous class I do. On the one hand because it is an additional instantiation and on the other hand because it is more difficult to identify at debug (when they are several in the same class).
And I can't see the reasons why I should prefer the use of an anonymous class for this case.
Maybe with my classes as an example the explanation will be easier.
for(Segmentf segment : new LinesfIterator(cube.getPoints(), cube.getIndices())) {
System.out.println(segment);
}
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, ? extends IPoint<N>>> implements Iterable<S>, Iterator<S> {
private N[][] points;
private int[] indices;
private int count;
public LinesPIterator(N[][] points, int[] indices) {
super();
this.points = points;
this.indices = indices;
}
protected abstract S instanciateIteration(final N[] pointDeb, final N[] pointFin);
#Override
public Iterator<S> iterator() {
return this;
}
#Override
public boolean hasNext() {
return count < (indices.length - 1);
}
#Override
public S next() {
return instanciateIteration(points[indices[count++]], points[indices[count++]]);
}
}
public class LinesfIterator extends LinesPIterator<Float, Segmentf> {
public LinesfIterator(Float[][] points, int[] indices) {
super(points, indices);
}
#Override
protected Segmentf instanciateIteration(Float[] point1, Float[] point2) {
return new Segmentf(point1, point2);
}
}

Abstract class constructor param vs. abstract method for final data

What are the pros/cons of using the abstract class constructor vs. an abstract method for passing final data to an abstract class?
Pass via constructor:
public abstract class MyAbstractClass<T> {
private final String type;
private final Function<String, T> factoryFn;
protected MyAbstractClass(String type, Function<String, T> factoryFn) {
this.type = type;
this.factoryFn = factoryFn;
}
public T doSomething(String value) { ... }
}
Pass via abstract method:
public abstract class MyAbstractClass<T> {
abstract String getType();
abstract T getFactoryFn(String value);
public T doSomething(String value) { ... }
}
I'm aware that the abstract methods can potentially be misused, because it doesn't enforce to always return the same value.
But apart from that, is it just a matter of personal preference, or are there any real (dis)advantages for using one over the other?
I hope I am understanding your question correctly..
Usually, when a property of a class is always held in a field, it is more concise to use an abstract constructor. For example, consider the two following scenarios....
// Scenario 1:
abstract class AClass {
final int field;
public AClass(int f) {
field = f;
}
public int getField() {
return field;
}
}
class Class1 extends AClass {
public Class1(int f) {
super(f);
}
// Class Unique Code...
}
class Class2 extends AClass {
public Class2(int f) {
super(f);
}
// Class Unique Code...
}
// Scenario 2:
abstract class AClass {
public abstract int getField();
}
class Class1 extends AClass {
final int field;
public Class1(int f) {
field = f;
}
#Override
public int getField() {
return field;
}
// Class Unique Code...
}
class Class2 extends AClass {
final int field;
public Class2(int f) {
field = f;
}
#Override
public int getField() {
return field;
}
// Class Unique Code...
}
Scenario 1 is shorter since the getter logic for field only needs to be specified once. Whereas in scenario 2, the getter logic must be overridden by both subclasses. I find scenario 2 to be redundant... why write the same code twice when you can use java inheritance to your advantage.
As a final note, I usually don't hold functions in fields unless totally necessary. Whenever you have a function in a field, it's usually a sign that an abstract function can be applied.
Here is your original code with my advice applied...
public abstract class MyAbstractClass<T> {
private final String type;
protected MyAbstractClass(String t) {
type = t;
}
protected abstract T applyFactoryFunction(String value);
public T doSomething(String value) { ... }
}
Hope this helped!

Changing method behaviour depending on subtype of 2 input parameters

I am trying to create a card game with a clean class design.
I would like to compare 2 cards and return the one with the highest "value".
I have an abstract card class and 2 classes inherited from it :
public abstract class Card {
...
//common method
public int getCardValue() { return this.cardValue; }
//comparison methods
public abstract Card compare(ColoredCard card);
public abstract Card compare(TrumpCard card);
}
public class ColoredCard extends Card {
//specific attribute
private Color cardColor;
...
//specific method
public Color getColor() { return this.cardColor; }
public Card compare(ColoredCard card) {
if(this.getColor() == card.getColor())
return this.getCardValue() > card.getCardValue() ? this : card;
return this;
}
public Card compare(TrumpCard card) {
return card;
}
}
public class TrumpCard extends Card {
...
public Card compare(ColoredCard card) {
return this;
}
public Card compare(TrumpCard card) {
return this.getCardValue() > card.getCardValue() ? this : card;
}
}
But it still throw an error whenever I try :
Card c = new ColoredCard(5);
Card c2 = new TrumpCard(1);
c.compareTo(c2); //error method compareTo not applicable to type of argument "Card"
I NEED to access whole subclass interface to do each of my comparison but also keep the comparison call "generic" (through Card superclass).
I would like to avoid to use instanceOf instruction or reflection if possible.
Thank you,
If it's possible, I would define an abstract method on the base class that lets the subclasses provide their absolute value. Then you can make the base class Comparable and implement a compareTo() method that uses this value. The value doesn't even need to be revealed publicly.
public static abstract class Card implements Comparable<Card> {
#Override
public int compareTo(Card other) {
return Integer.compare(this.value(), other.value());
}
protected abstract int value();
}
public static class ColoredCard extends Card {
#Override
protected int value() {
return 1;
}
}
public static class TrumpCard extends Card {
#Override
protected int value() {
return 10;
}
}
public static void main(String... args) throws Exception {
System.out.println(new TrumpCard().compareTo(new ColoredCard()));
System.out.println(new ColoredCard().compareTo(new TrumpCard()));
}
Prints:
1
-1
If that's no good, then you will need to use instanceof or something like the Visitor pattern or rethink the design.
For example, you could redesign so that rather than having a separate class for each card, you hold the kind of card as a field (perhaps using an enum). Then when you compare two cards you can compare the kinds of the two cards, won't need to use instanceof and can incorporate whatever logic you like.
E.g.
public static enum Kind {
COLORED,
TRUMP;
}
public static class Card {
private final Kind kind;
public Card(Kind kind) {
this.kind = kind;
}
public Kind kind() {
return kind;
}
}
public static void main(String... args) throws Exception {
Card trumpCard = new Card(Kind.TRUMP);
Card coloredCard = new Card(Kind.COLORED);
int i = compare(trumpCard, coloredCard);
}
public static int compare(Card card, Card other) {
if (card.kind().equals(other.kind())) {
return 0;
}
if (card.kind().equals(Kind.TRUMP)) {
return 1;
}
return -1;
}
So I found a way which work using Visitor pattern :
public interface ICardVisitor {
public Card visit(TrumpCard card);
public Card visit(ColoredCard card);
public void setSecondCard(ColoredCard card);
public void setSecondCard(TrumpCard card);
}
public class ComparisonVisitor implements ICardVisitor {
private TrumpCard trumpCard;
private ColoredCard coloredCard;
...
//contains comparison logic & instances of card subtypes
}
I also had to add an extra function (in addition to the classic accept(Visitor v) method) to my abstract Card class :
public abstract void setThisCardAsParameter(ICardVisitor v);
inside the concrete Card implementations :
public Card accept(ICardVisitor visitor) {
return visitor.visit(this);
}
public void setThisCardAsParameter(ICardVisitor v) {
v.setSecondCard(this);
}
This way the comparison class know each subtype for each card so he has access to all specific methods of a given child class.
The call is looking like this :
public static void main(String [] args) {
ICardVisitor cmp = new ComparisonVisitor();
Card c = new TrumpCard(1);
Card c2 = new ColoredCard(CardTypes.SPADES,1);
ICardVisitor cmp = new ComparisonVisitor();
c.setThisCardAsParameter(cmp);
Card winningCard = c2.accept(cmp);
}
If that design is bad or can be improved, please let me know it !

Best way to avoid explicit casts

I have a class hierarchy like below
Vehicle
|_ TransaportationVehicle has method getLoadCapacity
|_ PassengerVehicle has method getPassengerCapacity
and I have one more class Booking it have a reference to Vehicle.
Now whenever I have to call getPassengerCapacity or getLoadCapacity on vehicle reference I need to type cast vehicle to its concrete implementation like ((PassengerVehicle)vehicle).getPassengerCapacity() and this type of calls spans over multiple parts in the project. So is there any way with which I can avoid these type of casts and my code will look beautiful and clean?
Note: These are not actual classes I have taken these as an example to demonstrate current problem.
Obviously, when booking a Vehicle you need to distinguish at some point whether it’s a TransportationVehicle or a PassengerVehicle as both have different properties.
The easiest way would be to initiate two different Booking processes: one for vehicles that can transport goods, and one for vehicles that can transport passengers. As for how to differentiate between these two types of vehicles: you could add canTransportPassengers() and canTransportGoods() methods to Vehicle, the subclasses would then override these methods to return true where appropriate. Also, this way a vehicle that can transport both is possible, like a train.
If You want to use different method names then You must cast to concrete class.
But if You can make this methods return same type value and have same names You can use polymorphism for it. Create abstract method in Vehicle class and override it in each child.
A quick way I would accomplish this is to create a Generified Booking parent class.
public abstract class Booking<V extends Vehicle> {
protected abstract V getVehicle();
}
public class TransportationVehicleBooking extends Booking<TransaportationVehicle> {
#Override
protected TransaportationVehicle getVehicle() {
return new TransaportationVehicle();
}
}
public class PassengerVehicleBooking extends Booking<PassengerVehicle> {
#Override
protected PassengerVehicle getVehicle() {
return new PassengerVehicle();
}
}
Your Booking class will have all the logic that spans all the booking subclasses and some abstract method each subclasses will need to do effective calculations.
Then all you have to do is have reference to a Booking class and calling the relevant method required without having to worry about the "logistics" (get it) of the booking itself.
I hope this helps.
You method overriding concepts. You need to have all these method in the Parent class and same can be overriden in the child clasees.
You can then access all the methods from super class using Runtime polymorphism
Vehicle
public interface Vehicle {
public int getCapacity();
}
TransaportationVehicle
public class TransaportationVehicle implements Vehicle {
#Override
public int getCapacity() {
return getLoadCapacity();
}
private int getLoadCapacity() {
return 0;
}
}
PassengerVehicle
public class PassengerVehicle implements Vehicle {
#Override
public int getCapacity() {
return getPassengerCapacity();
}
private int getPassengerCapacity() {
return 0;
}
}
USAGE
Vehicle passenger = new PassengerVehicle();
passenger.getCapacity();
Vehicle transaportation = new TransaportationVehicle();
transaportation.getCapacity()
First try to extract an abstract method suitable for all vehicles. If you can't do this you can also use an often forgotten pattern - the visitor pattern. E.g.
Introduce a visitor interface
public interface VehicleVisitor {
public void visit(TransportationVehicle transportationVehicle);
public void visit(PassengerVehicle passengerVehicle);
}
add an accept method to the Vehicle
public interface Vehicle {
public void accept(VehicleVisitor visitor);
}
implement the accept method in the sub classes
public class PassengerVehicle implements Vehicle {
private int passengerCapacity;
public static PassengerVehicle withPassengerCapacity(int passengerCapacity) {
return new PassengerVehicle(passengerCapacity);
}
private PassengerVehicle(int passengerCapacity) {
this.passengerCapacity = passengerCapacity;
}
public int getPassengerCapacity() {
return passengerCapacity;
}
#Override
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
public class TransportationVehicle implements Vehicle {
private int loadCapacity;
public static TransportationVehicle withLoadCapacity(int loadCapacity) {
return new TransportationVehicle(loadCapacity);
}
private TransportationVehicle(int loadCapacity) {
this.loadCapacity = loadCapacity;
}
public int getLoadCapacity() {
return loadCapacity;
}
#Override
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
implement a visitor...
public class LoadSupported implements VehicleVisitor {
private boolean supported;
private int load;
public LoadSupported(int load) {
this.load = load;
}
public boolean isSupported() {
return supported;
}
#Override
public void visit(TransportationVehicle transportationVehicle) {
int loadCapacity = transportationVehicle.getLoadCapacity();
supported = load <= loadCapacity;
}
#Override
public void visit(PassengerVehicle passengerVehicle) {
supported = false;
}
}
...and use it
public class Main {
public static void main(String[] args) {
TransportationVehicle transportationVehicle1 = TransportationVehicle
.withLoadCapacity(5);
TransportationVehicle transportationVehicle2 = TransportationVehicle
.withLoadCapacity(10);
PassengerVehicle passengerVehicle = PassengerVehicle
.withPassengerCapacity(5);
LoadSupported loadSupported = new LoadSupported(7);
supportsLoad(transportationVehicle1, loadSupported);
supportsLoad(transportationVehicle2, loadSupported);
supportsLoad(passengerVehicle, loadSupported);
}
private static void supportsLoad(Vehicle vehicle,
LoadSupported loadSupported) {
vehicle.accept(loadSupported);
System.out.println(vehicle.getClass().getSimpleName() + "[" + System.identityHashCode(vehicle) + "]" + " does"
+ (loadSupported.isSupported() ? " " : " not ")
+ "support load capacity");
}
}
The output will be something like this
TransportationVehicle[778966024] does not support load capacity
TransportationVehicle[1021653256] does support load capacity
PassengerVehicle[1794515827] does not support load capacity
Assuming that passenger capacity is always an integer and load capacity could very well a big number depending on what is the unit for load. I would go ahead and create Vehicle class as follow:
class Vehicle {
Number capacity;
public Number getCapacity() {
return capacity;
}
public void setCapacity(Number capacity) {
this.capacity = capacity;
}
}
The reason I am using Number is so that I then use Integer in PassengerVehicle class and Double in TransporatationVehicle and that is because Integer and Double are subtype of Number and you can get away with a cast.
class TransportationVehicle extends Vehicle {
#Override
public Double getCapacity() {
//all I have to do is cast Number to Double
return (Double) capacity;
}
#Override
public void setCapacity(Number capacity) {
this.capacity = capacity;
}
}
Similarly the PassengerVehicle class as follow:
class PassengerVehicle extends Vehicle {
#Override
public Integer getCapacity() {
//Cast to Integer and works because Integer is subtype of Number
return (Integer) capacity;
}
#Override
public void setCapacity(Number capacity) {
this.capacity = capacity;
}
}
You can then use above classes to create vehicle object as follow:
public class Booking {
public static void main(String[] args) {
//
Vehicle transportationVehicle = new TransportationVehicle();
//assigning Double to setCapacity
transportationVehicle.setCapacity(new Double(225.12));
Vehicle passengerVehicle = new PassengerVehicle();
//assigning Integer to setCapacity
passengerVehicle.setCapacity(5);
System.out.println(transportationVehicle.getCapacity());
// output: 225.12
System.out.println(passengerVehicle.getCapacity());
// output: 5
}
}
On the side notes if you try to pass TransportationVehicle anything but Number or Double then you will get Exception and similarly if you pass PassengerVehicle anything but Number or Integer you will get exception.
I know that I am deviating from the scope of your question but, I really want to show how you can make your methods generics. This allow you to decide to return type of getCapacity() during coding which is very flexible. See below:
class Vehicle<T> {
//generic type T
T capacity;
//generic method getCapacity
public T getCapacity() {
return capacity;
}
//generic method setCapacity
public void setCapacity(T capacity) {
this.capacity = capacity;
}
}
class TransportationVehicle<T> extends Vehicle<T> {
#Override
public T getCapacity() {
return capacity;
}
#Override
public void setCapacity(T capacity) {
this.capacity = capacity;
}
}
class PassengerVehicle<T> extends Vehicle<T> {
#Override
public T getCapacity() {
return capacity;
}
#Override
public void setCapacity(T capacity) {
this.capacity = capacity;
}
}
As you can see above the generic methods and you can use them as follow:
Vehicle<String> vehicleString = new TransportationVehicle<String>();
vehicleString.setCapacity("Seriously!"); //no problem
Vehicle<Integer> vehicleInteger = new PassengerVehicle<Integer>();
vehicleInteger.setCapacity(3); //boxing done automatically
Vehicle<Double> vehicleDouble = new PassengerVehicle<Double>();
vehicleDouble.setCapacity(2.2); //boxing done automatically
You can decide the type while coding and if you supply a Vehicle<String> with capacity as Integer then you will get compile time error, so you won't be allowed.
System.out.println(vehicleString.getCapacity());
//output: Seriously!
System.out.println(vehicleInteger.getCapacity());
//output: 3
System.out.println(vehicleDouble.getCapacity());
//output: 2.2
I don't understand the example. How do you realize that you are dealing with a concrete type in the first place? Are you instanceOf-ing? Are you type matching?
If so your problem is way past casting...
Anyways when you have objects that must belong to the same family and algorithms which are not abstract and change according to the object being handled you typically use some sort of behavioral pattern like visitor, or the Bridge pattern.

Categories

Resources