Adrian Amiel Sanchez
11/22/2022, 4:53 PMSuch classes are useful for one-time use
.
interface Person {
val name: String
val age: Int
}
Option 1
---
fun Person(name: String, age: String): Person = object : Person {
override val name = name
override val age = age
}
Option 2
---
fun Person(name: String, age: String): Person = PersonImpl(name, age)
private class PersonImpl(
override val name: String,
override val age: String
) : Person
1. What’s the pros/cons between the two?
2. Which is more preferred?
3. What does one-time use
mean? Does it mean we can’t pass instances of anonymous classes around?Andre Theilacker
11/22/2022, 5:15 PMCasey Brooks
11/22/2022, 5:15 PMPerson
interface is just a data-holder, which is not a good use-case for anonymous objects. There’s not really a good reason to represent Person
as an interface instead of just using a data class
, it’s an unnecessary level of abstraction that makes the code harder to understand.
A one-time anonymous object is useful when doing local processing of data that benefits of the readability of discrete properties, but you really don’t need that class anywhere else. Take the following example, where we parse a list of strings into XYZ vectors and find their length: https://pl.kotl.in/wkR1FoHD9
Another use-case is when you have an interface which may have many different implementations, but those implementations are relatively simple and do not warrant having actual class declarations for each. Creating delegate functions with ReadOnlyProperty
or ReadWriteProperty
is one such example. As you can see in this file, there are lots of object expressions, but they’re all simple 1-liners (ReadOnlyProperty
is defined as a fun interface
which means you can drop the object :
part and just use a lambda)Casey Brooks
11/22/2022, 5:27 PMOnClickListener
or creating property delegates is something I do quite frequentlyAdrian Amiel Sanchez
11/22/2022, 5:35 PMYou usually would use an anonymous object when you need to implement an interface that will be used in only one place
A one-time anonymous object is useful when doing local processing of data that benefits of the readability of discrete properties, but you really don’t need that class anywhere elseThanks! These two seems to convey the same message. In this case, I’m only exposing the factory method
Person
as an API and any devs that need to create a Person
does not need to know about PersonImpl
class. Does that mean anonymous object can be used here? Just thinking that defining PersonImpl
is unnecessary boilerplateKevin Del Castillo
11/22/2022, 5:39 PMPerson
example is flawed? If you're talking about a person it makes more sense to have a data class
rather than an interface, I don't see how the implementation of the interface would have such an intricate logic that needs to be hidden, however if in this example the Person
interface represents any other component that maybe have a clear harder and complex implementation than just holding data, I'll go with the implementation in a private class:
interface Something
fun Something(): Something = SomethingImpl()
private class SomethingImpl : Something
Just because holding all the logic inside an anonymous object here wouldn't make too much senseCasey Brooks
11/22/2022, 5:48 PMPersonImpl
class, or whether it’s just “to avoid coupling” (which is not even true, since the class they create is still coupled to the interface). Java code usually leads too heavily on the interface/impl structure when it’s not really necessary and only makes the code harder to read, and it much less prevalent in Kotlin.
In the case where the data is reasonably complex and you can expect each consumer would do different things with it, then it’s advisable to use a concrete class instead of an object expression.Casey Brooks
11/22/2022, 5:51 PMPerson
. Does it represent a logged-in user, where the user may sign in via Twitter, Facebook, Google, etc. and each auth provider needs custom logic for defining what a “Person” is? Then yes, keep it as an interface. But if you only have 1 thing that could be a Person that you manage within the library, then you’re better off using a data class
instead of interface
, which gives you additional benefits of things like equals/hashcode and toString automaticallyCasey Brooks
11/22/2022, 5:52 PM