2014-11-11 21 views
5

Ich habe eine Java-Klasse, die ich unterklassieren möchte. Die Unterklasse dient nur zum Hinzufügen von Convenience-Methoden - es könnte alles mit externen Methoden geschehen, weil ich nur die öffentlichen Felder betrachte und nichts modifiziere.Scala - Erweitern eines Referenztyps ohne Unterklasse

Wenn die Basisklasse ein Werttyp war, würde ich Wert-Wrapper verwenden - extends AnyVal. Die Basisklasse ist jedoch ein Java-Referenztyp. Gibt es eine bessere Möglichkeit, die Unterklasse anders als zu erweitern?

+1

Was ist der Unterschied? Sind nicht alle Klassen in Scala Java-Referenztypen? Sie alle erweitern java.lang.Object. (Das ist eine ernste Frage, übrigens. Ich verstehe wirklich nicht, was Sie zu tun versuchen.) – markspace

+2

Wenn Sie es nicht erweitern möchten, könnten Sie das * Pimp My Library * -Muster verwenden. –

+1

Beachten Sie, dass Sie Wertklassen verwenden können, um Typen ohne Wert zu umbrechen. Eine Demonstration finden Sie unter [meine Antwort unten] (http://StackOverflow.com/a/26869791/334519). –

Antwort

10

Um Ihre zweite Absatz speziell Adresse, der Typ Sie mit einem Wert Klasse wickeln kann einen Referenztyp sein und vermeiden Sie noch die extra Objektzuordnung, die normalerweise am Umbruch beteiligt wäre. Zum Beispiel haben, wenn Sie diese impliziten Klassen bekommen:

implicit class MyInt(val underlying: Int) extends AnyVal { 
    def inc: Int = underlying + 1 
} 

implicit class MyString(val underlying: String) extends AnyVal { 
    def firstChar: Char = underlying.charAt(0) 
} 

implicit class MyNonValueClassString(val underlying: String) { 
    def firstCharNonValueClass: Char = underlying.charAt(0) 
} 

Und diesen Code, die sie verwendet:

println(42.inc) 
println("hello".firstChar) 
println("hello".firstCharNonValueClass) 

Sie mit -Xprint:flatten kompilieren können die entzuckert Version zu sehen (hier aus Gründen der Klarheit neu formatierte):

scala.this.Predef.println(
    scala.Int.box(Demo$MyInt.this.inc$extension(Demo.this.MyInt(42))) 
); 

scala.this.Predef.println(
    scala.Char.box(
    Demo$MyString.this.firstChar$extension(Demo.this.MyString("hello")) 
) 
); 

scala.this.Predef.println(
    scala.Char.box(
    Demo.this.MyNonValueClassString("hello").firstCharNonValueClass() 
) 
); 

Wie Sie sehen können, wird der firstChar Anruf nicht ein neues Objekt beinhalten.

2

Gunst Zusammensetzung über Vererbung.

In Ihrem Fall ist der beste Weg wahrscheinlich, eine Klasse mit der Java-Klasse als Attribut zu erstellen. Dann können Sie einfach die Methoden dieser Objekte delegieren und fügen Sie Ihre eigenen:

class MyClass(jo: JavaObject) { 
    def delegateMethod() = jo.method() 
    def newMethod() = // ... 
} 
Verwandte Themen