2011-10-26 9 views
0

私はトラックとセダンという2つのクラスを持っています。何らかのアクションが発生すると、TruckクラスのhashMapにセダンを追加します。マップは、セダンが現在トラックの貨物に入っていることを示している。私はトラックとセダンがお互いを知りたくないので、セダンのIDとセダンが追加したいトラックのIDを渡してセダンが呼び出せる方法をCarManagerで作った。その後、CarManagerはセダンがリストに追加されることをTruckに通知します。問題は、CarManagerがTruckに通知する方法と、そのaddSedanメソッドで必要なものがわからないことです。私はCarManagerの中にCarEntitiesのコレクションを持つHas​​hMapを持っています。トラックのaddCarメソッドは、インターフェイスにないのでCarManagerからアクセスできません。すべてのCarEntityがそれを使用するわけではないので、インターフェイスに追加したくありません。誰も助けることができますか?JavaのHashMapでオブジェクトのメソッドを呼び出す

public interface CarEntity { 
    String getId(); 
    double getSpeed(); 
    void move(); 
} 

public class CarManager { 
    private HashMap<String, CarEntity> hash = new HashMap<String, CarEntity>(); 
    public void addSedan(String carId, String truckId) { 
    ??? 
    hash.get(truckId).addCarr(carId); //I don't think this will work 
    } 

} 

public class Truck implements CarEntity { 
    private HashMap<String, CarEntity> cargo = new HashMap<String, CarEntity>(); 
    public void addCar(String id, CarEntity ce) { 
     cargo.put(id,ce); 
} 

public class Sedan implements CarEntity { 
    CarManager.addSedan("Car 1", "Truck 5"); 
} 

答えて

1

あなたはキャストを使用することはできませんし、instanceofはポリモーフィズムを使用する必要があり、その後、あなたのCarEntityインターフェースに2つのメソッドを追加する場合:

boolean canBeLoadedWithCars(); 
void addCar(CarEntity c) throws IllegalStateException; 

トラックが乗用車を搭載したので、trueを返すことにより、最初のmethofを実装することができます。他のものはfalseを返します。

addCarメソッドがTruckの場合、車はマップに追加されますが、他の実装では車でロードできないためIllegalStateExceptionがスローされます。

ので、管理者のaddCar方法は、私はそれを使用することはできません

CarEntity truck = hashMap.get(truckId); 
if (truck.canBeLoadedWithCars() { 
    truck.addCar(sedan); 
} 
+0

しかし、私はすべてのCarEntitiesがトラックに必要なときにそれらのメソッドを実装する必要があるという問題にぶつかります – Dan

+0

これらのメソッドの実装は非常に簡単です。 1行のコード。しかし、AbstractCarEntityクラスからデフォルトの実装を継承し、Truckクラスでのみオーバーライドすることができます。 –

+0

しかし、1つのクラスだけがそれを使用する場合、インターフェイスにいくつかのメソッドを持つことは悪い設計ではありませんか? – Dan

0

私はあなたが行うことができます一つのことが

CarEntity t = hash.get(truckId); 
if (t instanceof Truck) 
    downcast car entity to truck 
    call add car method 
+0

になります。私の場合、キャスティングは眉をひそめます。 – Dan

0

だと思い答えはアクションをやっている人に依存します。 Sedanがトラックに追加された場合は、すべてのトラックをマネージャーに追加するaddTruckメソッドが必要です。管理者は、MapTruckを格納します。

private Map<String, Truck> trucks = new HashMap<String, Truck>(); 
public void registerTruck(Truck truck) { 
    trucks.put(truck.getId(), truck); 
} 

そして、マネージャーのaddCar()方法はどうなる:

public void addCar(String truckId, CarEntity car) { 
    Truck truck = trucks.get(truckId); 
    // null handling needed here 
    truck.addCar(car); 
} 

代わりに、トラックが車を取る、なら、あなたの代わりに車を登録することができます。

private Map<String, Truck> trucks = new HashMap<String, Truck>(); 
private Map<String, Sedan> sedans = new HashMap<String, Sedan>(); 

public void registerTruck(Truck truck) { 
    trucks.put(truck.getId(), truck); 
} 
public void registerSedan(Sedan sedan) { 
    sedans.put(sedan.getId(), sedan); 
} 

public void addSedan(String sedanId, String truckId) { 
    Sedan sedan = sedans.get(sedanId); 
    Truck truck = trucks.get(truckId); 
    // null handling needed here 
    truck.addCar(sedan); 
} 

は、一般的に、我々はデカップリングを達成するためにJavaインタフェースを使用する:あなたは、両方の文字列IDであることする必要がある場合、あなたは両方の車やトラックを登録し、ような何かをする必要があります。 Truckクラスは、それがSedanであることを知らずにCarEntityを負荷に追加できる必要があります。この場合、TruckaddCar(CarEntity car)メソッドは正常です。 Sedanは、それがTruckにあり、すべてのトラックがCarEntityインターフェイスで公開されているメソッドであることを知ることはできません。この場合、マネージャーが遠ざかるかもしれません。

+0

私はまだ少し混乱しています。トラックHashMapはどこにありますか? CarManagerでは?なぜなら、CarManagerではなく、TruckクラスにあるHashMapにセダンを追加しようとしているからです。 – Dan

+0

マネージャーの 'Sedan'と' Truck'sを文字列IDとして参照したいのであれば、managerはtruckId - > truckとsedanId - > 'Sedan'からのマッピングを持たなければなりません。'Truck'に' CarEntity'オブジェクトのコレクションが残っています。 – Gray

+0

ああ、 'Truck.addCar()'にidフィールドは必要ありません。 'CarEntity'で' getId() 'を呼び出す必要があります。 – Gray