ehrt1974
ehrt1974

Reputation: 1186

generic container of a generic class in java

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

Answers (1)

Adam Bukowiecki
Adam Bukowiecki

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.
  • self() method - I added self() method to 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

Related Questions