Assigning a Parent object to a Child object Without casting in Java

狂风中的少年 提交于 2019-12-24 12:07:46

问题


I have a parent interface and a child interface which objects will implement. I've made a child interface because I want a specific VehicleEntity object say Truck to add itself to the HashMap in Car. A Truck will call VehicleManager's addToCar() method which add the Truck object into Car's hashMap. The issue I have is CarEntity ce = ve;. Netbeans is telling me to cast ve to CarEntity but I don't want to. Shouldn't the line of code be valid (assuming the the object the for loop is looking at is a Car object)? How can I fix this?

public interface VehicleEntity {
    getId();
    getSpeed();
    move();
    }

public interface CarEntity extends VehicleEntity{
    addToCar(String c);
}

public class Car implements CarEntity{
HashMap<String, VehicleEntity> cars = new HashMap<String, VehicleEntity>();

    public void addToCar(String c) {
       cars.add(c);
    }
}

public class VehicleManager {
    HashMap<String, VehicleEntity> vehicles = new HashMap<String, VehicleEntity>();

public void reportToCar(String id) {
    for (VehicleEntity ve : ve.values()) {
        if (ve.getId().equals(id)) {
            CarEntity ce = ve; // Issue here
        }
    }
}

回答1:


Really, that's not at all valid. You can move from the specific to the general without casting, but not back again. For instance, you can store an ArrayList in a List variable, but you can't take a List and put it into an ArrayList variable without casting. In the same way, you can't take a vehicle and say it is a car without explicitly casting.

So, in this case, since you know the vehicle is a car, cast to a car explicitly.




回答2:


I'm not entirely certain what it is you're trying to reach here, so I'm gonna list some corrected classes with my best guesses first...

public interface VehicleEntity {

    public String getId();

    public String getSpeed();

    public void move();

}

public interface CarEntity extends VehicleEntity {

    public void addToCar(String key, CarEntity c);

}

import java.util.HashMap;

public class Car implements CarEntity{ 
HashMap<String, VehicleEntity> cars = new HashMap<String, VehicleEntity>();

    @Override
    public void addToCar(String key, CarEntity car) {
       cars.put(key, this);
    }

    @Override
    public String getId() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getSpeed() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void move() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

... then show you a cool trick using generics:

import java.util.HashMap;

public class VehicleManager {

    HashMap<String, VehicleEntity> vehicles =
        new HashMap<String, VehicleEntity>();

    public <T extends VehicleEntity> T report(String id) {
        for(VehicleEntity ve : vehicles.values()) {
            if(ve.getId().equals(id)) {
                @SuppressWarnings("unchecked")
                T ce = (T)ve;
                return ce;
            }
        }
        return null;
    }

    public void test() {

        final Car c = report("test");

    }

}

I've parameterized the method report with a T extending VehicleEntity. It will return something of that type T. When using this in method test(), we've stated that we want a Car. Now some type inference is gonna go on, automatically calling method report for the type Car. If the VehicleEntity in the map with the given id isn't a Car, we'll get a ClassCastException since we're trying to cast to Car when calling thet method in that context.



来源:https://stackoverflow.com/questions/7909081/assigning-a-parent-object-to-a-child-object-without-casting-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!