Say we have these view model classes. You can imagine there's an entry in the UI for each subtype of InfoItem
, and each item contains some text and an icon.
abstract class InfoItem(text: String, icon: Image)
class Email(..): InfoItem(..) {
private email: String
}
class Map(..): InfoItem(..) {
private address: String
}
Now, we need to handle click events. When clicking on an item, we should navigate to the appropriate screen. You can imagine that there's a component on its own that provides these routing methods.
interface Router {
fun openEmailScreen(email: String)
fun openMaps(address: String)
}
I can think of two ways to go about this.
First, we could have a separate function/component, that would do the appropriate thing based on the InfoItem
type. However, in order to do that, we would have to make otherwise private properties of InfoType
, public. For example:
fun route(infoItem: InfoItem) {
when(infoItem) {
is Email -> router.openEmailScreen(infoItem.email) <-- email must be public
is Address -> router.openMaps(infoItem.address) <-- address must be public
}
}
Another approach would be to introduce an abstract function navigate(router: Router)
to InfoItem
and have each item implement it separately. This way, each item knows what it needs to do and can keep all the details to itself. However, we now have a direct dependency to Router
, which feels weird (although I can't explain why).
..
class Email(..): InfoItem(..) {
private email: String
fun navigate(router: Router) { router.openEmail(email) }
}
..
This example might be very simplistic, but I believe this issue applies to broader design as well.
email must be public
no it doesn't you can make it private with a getter and have a read-only property