11

Often I find myself in a situation where I have a superclass that has lots of optional parameters, and those same parameters need to also be optional parameters in its subclasses.

For example, the superclass:

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

Extending this class is a pain. Here's an example subclass:

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)

Note: I will answer this question with my solution. I am in search of a better solution.

Jire
  • 9,680
  • 14
  • 52
  • 87
  • 1
    Yet another reason to avoid inheritance :) If those parameters are optional why use them in constructor at all? Instead you could just declare regular property `var optionalProperty:String? = "DefaultValue"` in base class. – miensol Jan 24 '16 at 12:03

2 Answers2

6

The way I normally solve this problem is by creating a data class to represent the parameters.

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

I then take this class as a parameter in the constructors.

abstract class Plugin(val info: PluginInfo)

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

Then an example plugin can be implemented like this:

class ExamplePlugin : CyclePlugin(PluginInfo("Example Plugin", author = "Jire"), 8, TimeUnit.SECONDS)
Jire
  • 9,680
  • 14
  • 52
  • 87
5

Like @miensol mentioned, you can define your properties outside of the constructor.

abstract class Plugin(val name: String) {

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

}

Then you're able to define CyclePlugin with only the necessary name parameter:

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

Then for example, you can override some fields for ExamplePlugin:

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

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

}
Mibac
  • 8,990
  • 5
  • 33
  • 57