2012-03-14 13 views
16

Considerare seguente situazione:Java può fare qualcosa come la categoria nell'obiettivo C?

Object > MyClass > MyClassA, MyClassB 

Se voglio qualcosa nel livello di oggetto, per esempio, ho aggiunto printDetail(); Come posso farlo nell'implementazione Java? Inoltre, posso sovrascrivere tutto il metodo dell'oggetto. Ad esempio, ho bisogno di avere un intero nuovo .toString(), posso sovrascriverlo? Grazie.

risposta

28

No, non è possibile, non proprio in ogni caso. L'obiettivo C è un linguaggio tipizzato dinamicamente e con scope, che lo rende molto suscettibile a funzioni come le categorie. Il più vicino possibile a questo in Java è la strumentazione di classe tramite una libreria di manipolazione del codice byte come ASM o Javassist.

Ma in realtà, quando si utilizza un linguaggio OO fortemente tipizzato come Java, è necessario adottare le sue funzionalità piuttosto che cercare di duplicare quelle di un'altra lingua.

+0

ottima risposta .. !! –

+0

Anche se il commento è un po 'accademico, penso che il problema sia il factoring: ad es. se voglio un modo per randomizzare l'ordine delle cose in un array, potrei dire "semanticamente è più giusto un'azione che chiederei all'array di eseguire, quindi aggiungerò sintatticamente come metodo sull'array". Che non credo tagli contro essere fortemente dattiloscritto o orientato agli oggetti. Ma no, non è Javaish. – Tommy

+1

C# non è un linguaggio OO fortemente tipizzato? Perché C# offre questa capacità attraverso i metodi di estensione. Cosa c'è di male nel prendere roba buona da altre lingue? È un modo per progredire ... – obe

2

Tutte le classi Java eventualmente hanno java.lang.Object Per questo motivo, tutti i metodi Java classes inherit da Object. La metà di questi metodi è final e non può essere overridden. Tuttavia, gli altri metodi in Object possono essere sovrascritti.
Il metodo toString() nella classe Object viene utilizzato per visualizzare alcune informazioni relative a qualsiasi oggetto.
Quindi è possibile ignorare in base alle proprie auto ...
EX ..

public class Test{ 
    @Override 
    public String toString() { 
    /// staff 
    } 
} 
+0

Vedo. Io uso ruby, che mi consente di scavalcare l'oggetto di livello superiore. – DNB5brims

11

Come accennato nelle altre risposte, non c'è nulla di veramente come una categoria. Ho alcune soluzioni comuni che uso per alcune delle categorie nel mio codice obiettivo-c durante il porting su java. Molte delle mie categorie obiettivo-c esistono perché non voglio estendere le classi base iOS ma voglio aggiungere alcune funzionalità a quella classe. Molte di queste categorie obiettivo-c non aggiungono proprietà usando objc_SetAssociatedObject. Per quei casi uso una classe helper statica in Java. Diamo un'occhiata ad un esempio usando NSString e String. Aggiungerò funzionalità a entrambi per aggiungere virgolette alla stringa. Supponiamo che questo sia utile e non esiste ai fini dell'illustrazione. In Objective-C potremmo avere:

@interface NSString (MyCategory) 

/** 
* Creates and autoreleased image from self. 
*/ 
- (NSString*)quotedString; 

@end 

@implementation NSString (MyCategory) 

- (NSString *)quotedString 
{ 
    return [NSString stringWithFormat:@"\"%@\"", self]; 
} 

@end 

si potrebbe chiamare questo da un posto come questo:

NSString *myString = @"When you're curious, you find lots of interesting things to do."; 
NSString *quotedString = [myString quotedString]; 

Ecco come vorrei implementare questo in Java:

public class StringHelper { 

    public static String quotedString(String that) { 
     return '"' + that + '"'; 
    } 
} 

E per chiamare it:

String myString = = "When you're curious, you find lots of interesting things to do."; 
String quotedString = StringHelper.quotedString(myString); 

Se si pensa ai metodi di categoria come metodi che inviano automaticamente la variabile autonoma come primo argomento del metodo (anche se invisibile), ciò ha ancora più senso.

Per esempio, se non vorrei estendere l'oggetto specifico, potrei fare qualcosa di simile:

public class ObjectHelper { 

    public static void printDetail(Object that) { 
     // do what it takes; 
    } 
} 

AGGIORNAMENTO: Un commentatore ha chiesto per le limitazioni.

Le limitazioni sarebbero che il codice si trova in una classe statica separata. Non è conveniente come una categoria. Devi ricordare quei nomi di classe, o trovarli, e non otterrai il completamento automatico sui metodi degli oggetti originali nell'help. Inoltre, non è possibile utilizzare proprietà o attributi a livello di oggetto come si ottiene con objc_SetAssociatedObject. È possibile utilizzare una mappa hash e creare qualcosa di simile con l'istanza dell'oggetto originale come chiave hash.

public class StringHelper { 
    private static Map<String, Integer> order = new HashMap(); 

    public static int getOrder(String that) { 
     if(that == null) { return 0; } 
     Integer ret = StringHelper.order.get(that); 
     if(ret == null) { return 0; } 
     else { return ret; } 
    } 
    public static void setOrder(String that, int order) { 
     if(that != null) { 
      StringHelper.order.put(that, order); 
     } 
    } 
} 

ci sono anche scontri nome con la classe originale, che sarebbe più di un vantaggio. Le collisioni di nomi nelle categorie obiettivo-c sono considerate cattive.

+0

Questa risposta mi piace di più perché mi offre una soluzione alternativa. Grazie! –

+0

@ptoinson Quali sono i limiti se confrontiamo questo modo con la categoria in iOS? – NghiaDao

+0

@NghiaDao - Limitazioni aggiunte a un aggiornamento della risposta. – ptoinson

Problemi correlati