2016-01-24 3 views
7

Oft finde ich mich in einer Situation, wo ich eine Superklasse habe, die viele optionale Parameter hat, und diese gleichen Parameter müssen auch optionale Parameter in seinen Unterklassen sein.Kotlin: Wie kann ich Code-Duplizierung in Konstruktoren vermeiden?

Zum Beispiel die Oberklasse:

abstract class Plugin(val name: String, val version: String = "1.0", 
         val author: String = "", val description: String = "") 

diese Klasse erstreckt sich ein Schmerz. Hier ist ein Beispiel Unterklasse:

abstract class CyclePlugin(name: String, version: String = "1.0", author: String = "", 
         description: String = "", val duration: Int, val durationUnit: TimeUnit 
         = MILLISECONDS) : Plugin(name, version, author, description) 

Hinweis: Ich werde diese Frage mit meiner Lösung beantworten. Ich bin auf der Suche nach einer besseren Lösung.

+1

Ein weiterer Grund, Vererbung zu vermeiden :) Wenn diese Parameter optional sind, warum sie überhaupt im Konstruktor verwenden? Stattdessen könnten Sie einfach die reguläre Eigenschaft 'var optionalProperty: String? = "DefaultValue" 'in der Basisklasse. – miensol

Antwort

5

Wie @miensol erwähnt, können Sie Ihre Eigenschaften außerhalb des Konstruktors definieren können.

abstract class Plugin(val name: String) { 

    open val version: String = "1.0" 
    open val author: String = "" 
    open val description: String = "" 

} 

Dann sind in der Lage Sie CyclePlugin nur mit dem notwendigen name Parameter zu definieren:

abstract class CyclePlugin(name: String, val duration: Int, 
          val durationUnit: TimeUnit = MILLISECONDS) : Plugin(name) 

Dann zum Beispiel, können Sie einige Felder für ExamplePlugin außer Kraft setzen:

class ExamplePlugin : CyclePlugin("Example Plugin", 8, TimeUnit.SECONDS) { 

    override val author = "Giovanni" 
    override val description = "This is an example plugin" 

} 
+0

Was ist, wenn 'CyclePlugin' nicht abstrakt ist und mit diesen optionalen Parametern initialisiert werden kann? – BakaWaii

5

Die Art, wie ich normalerweise dieses Problem löse, besteht darin, eine Datenklasse zu erstellen, die die Parameter darstellt.

data class PluginInfo(val name: String, val version: String = "1.0", 
         val author: String = "", val description: String = "") 

Ich nehme dann diese Klasse als Parameter in den Konstruktoren.

abstract class Plugin(val info: PluginInfo) 

abstract class CyclePlugin(info: PluginInfo, val duration: Int, 
          val durationUnit: TimeUnit = MILLISECONDS) : Plugin(info) 

ein Beispiel Plugin kann dann wie folgt umgesetzt werden:

class ExamplePlugin : CyclePlugin(PluginInfo("Example Plugin", author = "Jire"), 8, TimeUnit.SECONDS)