2012-08-03 12 views
9

I'm get a ClassCastException ogni volta che provo a trasmettere un BufferedImage (parent) ad un AdvancedBufferedImage (child) che ho esteso me stesso, ho non sovrascritto nessun metodo e ho implementato tutti gli appaltatori senza modificarlicasting genitore a figlio - BufferedImage oggetto

Sto gettando questa eccezione ogni volta che provo a creare un AdvancedBufferedImage di File usando il metodo ImageIO.read().

File file = new file(path); 
AdvancedBufferedImage image = (AdvancedBufferedImage) ImageIO.read(file); 

Sembra che non ci dovrebbero essere problemi, quale potrebbe essere il problema?

risposta

15

Downcasting come questo non è consentito.

La soluzione preferita sarebbe quella di creare un costruttore di AdvancedBufferedImage, prendendo come parametro un BufferedImage. Con quello si potrebbe fare quanto segue.

File file = new file(path); 
AdvancedBufferedImage image = new AdvancedBufferedImage(ImageIO.read(file)); 

Qui il costruttore di AdvancedBufferedImage può decidere come convertire correttamente un BufferedImage in una avanzata ..

+0

Quindi suggerisci di modificare la relazione di AdvancedBufferedImage con BufferedImage, in modo che HAS A non sia IS A? –

+0

Esattamente. Questo approccio ti consente di delegare i metodi che non vuoi implementare tu stesso e di aggiungere ancora funzionalità aggiuntive. Dovrai solo avvolgere la classe esistente. –

+6

solo un avviso c'è uno strumento utile per fare proprio questo in eclissi, creare una classe che ha l'istanza della classe che si desidera delegare, fare clic destro sul membro, 'delegare metodi'. molto utile per grandi classi –

-1

Il tuo downcast avrà successo solo se l'oggetto che stai provando a trasmettere è in realtà un'istanza della classe a cui stai lanciando.

4

Non è possibile eseguire il cast di una classe PARENT in una classe CHILD a meno che il riferimento della classe PARENT non contenga un'istanza della classe CHILD o delle sue classi derivate.

Nel tuo caso, ImageIO.read(file) restituisce un'istanza di BufferedImage, che è la classe base. Ciò funzionerà solo se ImageIO.read(file) restituisce l'istanza di AdvancedBufferedImage o le sue sottoclassi.

Quando si estende una classe, la classe derivata eredita alcune proprietà dalla classe base, tuttavia, la classe base non guadagna nulla. Come risultato di ciò, poiché l'istanza della classe derivata ha tutte le proprietà della classe base, un riferimento della classe base può contenere l'istanza della classe derivata, vale a dire che è possibile eseguire il cast di una classe DERIVED alla classe BASE. Ora, la classe derivata può aggiungere alcune nuove proprietà e la classe base non è mai a conoscenza di queste proprietà. Quindi un cast dalla classe BASE a DERIVED è ovviamente errato.

3

Downcasting in Java

downcasting non è andare a lavorare in questo modo. Vedere la risposta nel post precedente. In alternativa, che ne è di fare un metodo factory statico che prende BufferedImage e restituisce un'istanza della classe creata con l'oggetto restituito da ImageIO.read()?

Ad esempio:

private AdvancedBufferedImage(BufferedImage bi) { 
    // build your AdvancedBufferedImage from bi 
    ... 
} 

public static AdvancedBufferedImage buildABI(BufferedImage bi) { 
    return new AdvancedBufferedImage(bi) 
+0

vedo ciò che si sta cercando di dire, ma in questo caso ci sono parametri nella contractor per le quali non ci sono getter, Quindi è necessario implementare anche –

+0

Quindi penso che la composizione sia un'idea migliore dell'ereditarietà nel tuo caso. La tua classe possiede un oggetto di BufferedImage invece di estenderlo? – Carl

0

BufferedImagenon è unAdvancedBufferedImage e così il cast non riesce.

È possibile estendere la funzionalità di BufferedImage, ma il metodo read restituisce comunque solo un BufferedImage. La fusione non forza il riferimento a diventare o a comportarsi come il tipo desiderato.

probabilmente avrete bisogno di avvolgere un BufferedImage nella classe AdvancedBufferedImage, allora si può passare in giro e manipolare il vostro corso avanzato.

2

In generale, non è possibile trasmettere classi di genitori a classi di bambini. È come forzare a lanciare un animale per un cane. Un cane è un animale, ma l'altro modo non è sempre vero, quindi il compilatore Java non ti permetterà di farlo.

Vedere object inheritance. è consentito

2

bassi, ma deve un'istanza effettiva del bambino:

class A { 
    String name = "a"; 
    A(){}; 
} 

class B extends A { 
} 

public class Main { 
    public static void main(String[] args) { 
    A a = new B(); // must a b instance 
    B b = new B(); 
    b = (B)a; 
    System.out.println(b.name); 

    } 
} 
Problemi correlati