Reputation: 1186
What should I write for "self" in Java? What I want "self" to mean here is "whatever class this concrete implementation of Vehicle is". Is that possible in Java?
import java.util.ArrayList;
import java.util.List;
abstract class Vehicle {
private Garage<self> garage;
void setGarage(Garage<self> g) {
this.garage = g;
g.vehicles.add(this);
}
}
class Car extends Vehicle {
}
class Garage<T extends Vehicle> {
List<T> vehicles = new ArrayList<>();
void addVehicle(T t) {
vehicles.add(t);
}
}
public class GenericFoo {
public static void main(String[] args) {
Garage<Car> carGarage = new Garage<>();
Car c = new Car();
carGarage.addVehicle(c);
c.setGarage(carGarage);
}
}
Upvotes: 0
Views: 523
Reputation: 138
It's possible to create something equivalent but requires some additional effort. Hava a look at below code:
import java.util.ArrayList;
import java.util.List;
public class GenericsSample {
public static void main(String[] args) {
Garage<Car> carGarage = new Garage<>();
Car c = new Car();
carGarage.addVehicle(c);
c.setGarage(carGarage);
}
abstract static class Vehicle<T extends Vehicle<T>> {
private Garage<T> garage;
void setGarage(Garage<T> g) {
this.garage = g;
g.vehicles.add(self());
}
abstract T self();
}
static class Car extends Vehicle<Car> {
@Override
Car self() {
return this;
}
}
static class Garage<T extends Vehicle<T>> {
List<T> vehicles = new ArrayList<>();
void addVehicle(T t) {
vehicles.add(t);
}
}
}
What's important here:
Vehicle
class parametrization - in fact, T
type is Vehicle
itself. We need it to be able to get actual type from parent level. In our case, T
represents Car
(and can represent any subclass actually). Vehicle<T extends Vehicle<T>>
may look a bit tricky but, in fact, it's quite easy to understand - T
is a "reference" to subclass from superclass.Vehicle
class. Please notice that self()
returns T
, not Vehicle
, what means that type of returned object is this concrete, implementation class. Each implementation has to just return this
.Hope it solves your problem.
Upvotes: 1