How does the Liskov Substitution Principle apply to function return types? - solid-principles

The Liskov Substitution Principle states that:
Objects in a program should be replaceable with instances of their sub-types without altering the correctness of that program.
Assuming that:
interface Iterable<T> {
fun getIterator(): Iterator<T>
}
interface Collection<T> : Iterable<T> {
val size: Int
}
interface List<T> : Collection<T> {
fun get(index: Int): T
}
interface MutableList<T> : List<T> {
fun set(index: Int, item: T): Unit
}
When LSP is applied to input parameters, the lowest-level abstraction should be applied:
DO
fun foo(items: Iterable<Any>) { ... }
DON'T
fun foo(items: List<Any>) { ... }
But, does LSP apply to function return types, and if so, does the reverse apply?
fun bar(): Iterable<Any> { ... }
OR
fun bar(): List<Any> { ... }

Yes and yes. In order to comply with the LSP, argument types in an overriding method must be contravariant, as you point out. The reverse is true for the return type -- this must be covariant, i.e. of the same type, or a more specific type, as the return type in the method being overidden.
Think of the slogan "demand no more, promise no less." Let's say the superclass method returns a Rectangle. This method can be overidden to return a Square, as this "promises more," but not to return a Shape, as this would "promise less."

Related

Referencing overloaded top-level Kotlin functions reflectively

In brief, how can one reference / iterate reflectively over overloaded top-level functions in Kotlin, such as kotlin.io.println?
Given the following:
object Bar {
fun foo(x: Int) = Unit
fun foo(x: Byte) = Unit
fun foo(x: Float) = Unit
}
I can iterate over the various overloads of foo by doing:
fun main() {
Bar::class.memberFunctions
.filter { kFunction -> kFunction.name == "foo" }
.forEach { kFunction -> println(kFunction) }
}
Which produces:
fun com.example.Bar.foo(kotlin.Byte): kotlin.Unit
fun com.example.Bar.foo(kotlin.Float): kotlin.Unit
fun com.example.Bar.foo(kotlin.Int): kotlin.Unit
However, if the various overloads of foo are defined top-level (outside of a class or object definition) such as simply:
fun foo(x: Int) = Unit
fun foo(x: Byte) = Unit
fun foo(x: Float) = Unit
Then there doesn't seem to be a way to reference them.
I tried being tricky using a top-level function in my example (such as main) to access the synthetic class:
::main::class.memberFunctions
.filter { kFunction -> kFunction.name == "foo" }
.forEach { kFunction -> println(kFunction) }
But it pukes on the fact that it's synthetic:
Exception in thread "main" java.lang.UnsupportedOperationException: This class is an internal synthetic class generated by the Kotlin compiler, such as an anonymous class for a lambda, a SAM wrapper, a callable reference, etc. It's not a Kotlin class or interface, so the reflection library has no idea what declarations does it have. Please use Java reflection to inspect this class.
How can I reference top-level overloaded functions in Kotlin?
More specifically, top-level overloaded functions defined in other packages / modules such as kotlin.io.println?
Top level functions by definition don't have a declaring class.
::println.javaClass.declaringClass //will return null
so you don't have a class to use reflection on, and consequently, you can't enumerate the top level members of a package.(Some magic can be done though, if you are willing to trade your soul)
The only way you can reference ambiguous top level functions is by helping the compiler to resolve the ambiguity like this:
val functionReference: (Int)->Unit = ::foo
and then you can call functionReference()

Is it possible to enable/disable a custom deserializer depending on the API endpoint being called?

I'm accessing a JSON API which has 2 kinds of endpoints:
the first kind returns a list of objects of the same type (Symptom, ChronicDisease...)
the second kind (a search function) returns a mixed list of objects of different types (those types are the same than can be returned by the first kind of API)
In the second case, each item of the list has a type field telling which is the type of the object. This field doesn't exist in the first case.
I would like to use the default deserializer for the first kind of API and a custom deserializer for the second kind of API. Is it possible?
If I only use the default deserializer, API calls of the first kind will work but I'm unable to perform a search.
If I enable the following deserializer, the search will work but the deserializer is also used when using the first kind of API and it fails because the type field is missing.
Custom deserializer I'd like to use:
class SearchableItemDeserializer : JsonDeserializer<SearchableItem>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): SearchableItem {
val root : JsonNode = p.readValueAsTree()
val type : String = root.get("type").asText()
when(type){
"symptom" -> {
return ObjectMapper().readValue(root.asText(), Symptom::class.java)
}
"symptom_group" -> {
return ObjectMapper().readValue(root.asText(), SymptomGroup::class.java)
}
"diagnosis" -> {
return ObjectMapper().readValue(root.asText(), Diagnose::class.java)
}
"chronic_disease" -> {
return ObjectMapper().readValue(root.asText(), ChronicDisease::class.java)
}
}
throw Exception("Unable to deserialize type $type")
}
}
Interface common to Symptom, SymptomGroup, Diagnose and ChronicDisease:
#JsonDeserialize(using = SearchableItemDeserializer::class)
interface SearchableItem
It's possible. You can extent Converter.Factory to create you custom converter. Probably most dumb and direct way would be to add check for specific retrofit annotation inside "requestBodyConverter" or "responseBodyConverter" methods.
Something like:
class CustomConverter : Converter.Factory() {
override fun responseBodyConverter(type: Type,
annotations: Array<Annotation>,
retrofit: Retrofit): Converter<ResponseBody, *>? {
return responseConverter(*annotations)
.responseBodyConverter(type, annotations, retrofit)
}
private fun responseConverter(vararg methodAnnotations: Annotation): Converter.Factory {
return when {
endpoint1(*methodAnnotations) -> converter1
endpoint2(*methodAnnotations) -> converter2
else -> defaultConverter
}
}
override fun requestBodyConverter(type: Type,
parameterAnnotations: Array<Annotation>,
methodAnnotations: Array<Annotation>,
retrofit: Retrofit): Converter<*, RequestBody>? {
//same approach here
}
fun endpoint1(vararg annotations: Annotation): Boolean {
//condition check here
}
fun endpoint2(vararg annotations: Annotation): Boolean {
//and here (if needed)
}
Just add your endpoints 1/2 implementation (probably just compare #Get() contents with certain pattern or something like that) and repeat same instruction for requestConverter.
When ready, just add it to retrofit:
return Retrofit.Builder()
.baseUrl(url)
.client(client)
.addConverterFactory(CustomConverter())
.build()

Using 'this' in Kotlin initializer - alternative solution, or safe to ignore?

I have a class that registers itself as an event handler, with an event service:
interface CommunicationService {
fun sendActivationMessage(toEmail: String)
}
abstract class EventCommunicationService : CommunicationService, AbstractEventHandler {
constructor(eventService: EventService) {
eventService.registerListener(this)
}
override fun onEvent(event: Event) {
if (event.type == EventType.USER_CREATED) {
sendActivationMessage(event.userEmail)
}
}
}
The idea being there can be an EmailCommunicationService, or a mocked testing version, etc. which don't all need to register themselves as listeners for when a user is created.
However Kotlin complains that I'm:
Leaking 'this' in constructor of non-final class EventCommunicationService
Which, well, I am. I could easily ignore the warning - but is there a better approach?
I've tried using an init { } block instead of a constructor, but the warning is the same.
I basically want a "post-construct" callback or similar that can be used to let this service register itself with the EventService provided in the constructor since that's the point of this intermediate type.
I understand why this is a problem - but I'm not sure how to reason my way to fixing it.
init blocks are really part of the constructor (in JVM terms), so that wouldn't help with the problem. It is very much not safe to ignore in general: see Leaking this in constructor warning for reasons (just ignore the accepted answer, its comments contain the real meat and so does Ishtar's answer).
One option (assumes that all subclasses have no-argument constructors, though it could be extended):
abstract class <T : EventCommunicationService> EventCommunicationServiceCompanion(private val creator: () -> T) {
operator fun invoke(eventService: EventService): T {
val obj = creator()
eventService.registerListener(obj)
return obj
}
}
// a subclass of EventCommunicationService:
class MyService private constructor () : EventCommunicationService {
companion object : EventCommunicationServiceCompanion<MyService>(MyService::new)
}
To create a MyService, you still call MyService(eventService), but this is actually the companion object's invoke method and not the constructor.

Kotlin: Generic function as return type?

In Kotlin, is it possible to declare a generic function type as the return type of a function?
What I want to achieve would look like this in Java:
interface Factory {
static Factory INSTANCE = new FactoryImpl();
<T> T create(String name, Class<T> type);
}
class PrefixedFactory implements Factory {
private final String prefix;
PrefixedFactory(String prefix) {
this.prefix = prefix;
}
#Override
public <T> T create(String name, Class<T> type) {
return Factory.INSTANCE.create(prefix + name, type);
}
}
(Note that in the example I access the Factory instance using the static field to avoid passing a generic function as a parameter, which would present its own problems in Kotlin).
I would like convert the prefixer to a kotlin function, but it seems to be impossible to declare a generic function as the return type:
fun prefixer(prefix: String): <T> (String, KClass<T>) -> T { TODO() }
This of course does not compile. It seems to me that this is a limitation compared to Java's functional interfaces. Is there a way to accomplish this, or a workaround?
(Edit) Clarification
I want the actual result function to be generic. If I do
fun <T: Any> prefixer(prefix: String): (String, KClass<T>) -> T { TODO() }
as the current answers suggest; I don't get a generic function, instead I get (String, KClass<Foo>) -> Foo if I call prefixer<Foo>(""). So that function can only be called with Foo, while the factory function prefixer in that case is generic, the result is not. I hope that clears up the misunderstandings.
My use case is in a Gradle plugin, where I wrote a helper method similar to this one that applies some defaults to each task created:
val myPrefix = "..."
val project: Project = <from context>
fun <T: Task> String.task(type: KClass<T>, doConfig: T.() -> Unit) {
project.tasks.create("$prefix$this", type.java, { it.doConfig() })
}
Note that the project comes in as closure. Now I want to reuse that helper in a different plugin, so I would like to create this function using a factory for different project instances.
You're doing it almost correctly. You only need to define the generic part at the prefixer function directly.
fun <T: Any> prefixer(prefix: String): (String, KClass<T>) -> T { TODO() }
Depending on you actual implementation, you could have a look at the reified keyword.
No, it isn't possible (as far as I know). The technical term for such a type is "higher-kinded type" and very few languages support them, on JVM I only know of Scala.
If someone asked me the same question without having an interface like Factory, I'd suggest creating exactly this interface as a workaround.
The following line does compile:
fun <T : Any> prefixer(prefix: String): (String, KClass<T>) -> T = TODO()
First, the generic deceleration should be right after the fun keyword.
Then it has has to be declared as type Any. The default is Any? but KClass only takes Any.
Although I was disappointed to read #Alexey's answer, I found a more streamlined workaround taking advantage of Kotlin's operators. The following makes it look more like a lambda when used:
private class Prefixer(private val: String) {
operator fun <T> invoke(name: String, type: Class<T>): T {
TODO()
}
}
To use it:
val createMy = Prefixer("MyPrefix")
val result = createMy("Configuration", Configuration::class.java)
Feel free to replace with KClass where necessary. I was actually using this for a slightly different purpose.

call one constructor from another constructors in one class

I've encountered the following question online.
If we call one constructor from another in a class, what will happen?
Can anyone give me some hints?
in java also its possible with the power of the this keyword. check out the example given below.
public class A {
public A() {
//this("a");
System.out.println("inside default Constructor");
}
public A(String a){
this();
System.out.println("inside Constructor A");
}
}
This concept is called constructor chaining. If it's c# i found this saying it's possible Is nesting constructors (or factory methods) good, or should each do all init work
This example from MSDN clarifies it
To add delegating constructors, constructor (. . .) : constructor (. . .) syntax is used.
class class_a {
public:
class_a() {}
// member initialization here, no delegate
class_a(string str) : m_string{ str } {}
// can’t do member initialization here
// error C3511: a call to a delegating constructor shall be the only member-initializer
class_a(string str, double dbl) : class_a(str) , m_double{ dbl } {}
// only member assignment
class_a(string str, double dbl) : class_a(str) { m_double = dbl; }
double m_double{ 1.0 };
string m_string;
};
Read answers from Can I call a constructor from another constructor (do constructor chaining) in C++? too.