0

How can I create an instance of InfoA that contains also title. Do I need to modify the classes?

Can't specify the title.

Also, do I need to create setters for it? To not access with the _

val info = InfoA(_subtitle = "SUBTITLE", title = ...)
  open class Info(
     open val action: Action = Action(),
     open val title: String? = ""
  ) {
    fun hasAction(): Boolean = action.hasAction()
  }

  class InfoA(
    private val _subtitle: String? = "",
    private val _image: String? = "",
    private val _backgroundImage: String? = "",
    private val _backgroundColor: String? = null,
    private val _foregroundColor: String? = null,
    private val _borderColor: String? = null
  ) : Info() {

    val subtitle: String
      get() = _subtitle.orEmpty()

    val image: String
      get() = _image.orEmpty()

    val backgroundImage: String
      get() = _backgroundImage.orEmpty()

    val backgroundColor: Int?
      get() = if (_backgroundColor != null) convertRgbStringToColorInt(_backgroundColor) else null

    val foregroundColor: Int?
      get() = if (_foregroundColor != null) convertRgbStringToColorInt(_foregroundColor) else null

    val borderColor: Int?
      get() = if (_borderColor != null) convertRgbStringToColorInt(_borderColor) else null
  }
Praveen P.
  • 976
  • 2
  • 11
  • 23

1 Answers1

2

As the code is written, title is a val, so it can't be changed from its initial value — which is empty string if (as in the case of InfoA) something calls its constructor without specifying another value.

If it were changed to be a var, then it could be changed later, e.g.:

val info = InfoA(_subtitle = "SUBTITLE").apply{ title = "..." }

Alternatively, if you want to keep it a val, then InfoA would need to be changed: the most obvious way would be to add a title parameter in its constructor, and pass that up to Info:

class InfoA(
    title: String? = "",
    // …other fields…
) : Info(title = title) {

Note that this way, InfoA can never use Info's default value for title, so you may need to duplicate that default in InfoA's constructor.

The need to duplicate superclass properties in a subclass constructor is awkward, but there's currently no good way around it.  (See e.g. this question.)  If there are many parameters, you might consider bundling them together into a single data class, which could then be passed easily up to the superclass constructor — but of course users of the class would need to specify that.  (Some people think that having more than a few parameters is a code smell, and that bundling them together can often improve the design.)

gidds
  • 16,558
  • 2
  • 19
  • 26
  • @PraveenP. Thanks for accepting my answer.  (But please note that on this site it's usually better to wait for a day, to give people who are busy or in other time-zones a chance.  Impossible as it may seem, someone might theoretically be able to write an even better answer than mine :-) – gidds Dec 18 '20 at 12:06
  • Also, I realise I didn't address your point about setters: those would only be possible if you changed the `val`s to `var`s; but it looks like you wouldn't need to override _both_ getters and setters to get the behaviour you want.  Though you shouldn't be afraid of nullable values; Kotlin is well set up to handle them safely, so in a case like this I'd probably look at using only the ‘bare’ properties defined in the constructor, without providing non-nullable versions at all. – gidds Dec 18 '20 at 12:08