What are the differences between a companion object function and package level functions? - kotlin

Whats the difference between having a function on a companion object and having the function at package level?
class Foo {
companion object {
fun bar() = println("bar")
}
}
fun bar() = println("bar")
You can call both pretty similar
class B {
fun print() {
Foo.bar()
}
fun print2() {
bar()
}
}

Related

Kotlin: Can I assign a function to a variable in a companion object from main?

New to kotlin, wondering if it's possible to dynamically assign
a function to a companion object's variable. Read the docs and some answers here but there's no mentioning about this.
class Printer {
companion object {
fun printAnything() {
println("printing anything..")
}
}
}
fun printA() {
println("printing A!")
}
fun main(args: Array<String>) {
printA()
Printer.printAnything = :: printA // doesn't compile, perhaps a different way?
}
You can't reassign a function that was declared with fun. It will always point to the same function. But you can make a var that holds a reference to a function. A var or val property holding a function can be invoked as a function, the same as if it was a fun declaration.
fun defaultPrintAnything() {
println("printing anything...")
}
var printAnything = ::defaultPrintAnything
fun printA() {
println("printing A!")
}
fun main() {
printAnything() // calls defaultPrintAnything
printAnything = ::printA
printAnything() // calls printA
}
You can make a variable like this anywhere you like, whether it's in a companion object or not. So yes, you can make your Printer companion object this way:
class Printer {
companion object {
var printAnything = {
println("printing anything..")
}
}
}

Referring the class that extends this class in a function

https://pl.kotl.in/WJxo0DujU (below is the code in the link)
open class A() { }
class B(): A() {
fun pew2() { }
}
fun <a: A> a.pew() = apply { }
fun main() {
val b = B()
b.pew().pew2()
}
Is there a way to have the function pew() in class A (not in A's companion object) and still be able to type b.pew().pew2() (not b.apply { pew().pew2() })?
You could create the pew() method in A and have the method return the instance itself:
open class A() {
fun pew() = this
}
class B(): A() {
fun pew2() { }
}
fun main() {
val b = (B().pew() as B).pew2()
}
You can override the function in B and narrow the return type.
open class A() {
open fun pew(): A {
//...
return this
}
}
class B: A() {
fun pew2() { }
override fun pew(): B {
super.pew()
return this
}
}
Kotlin doesn't have a self type that would make these kinds of chainable functions easier to implement, but the apply function makes chainable functions that return the same object unnecessary.

Is it possible to verify at compile time whether the required function is called for the Factory Class in Kotlin?

class ModelFactory {
fun setA() : ModelFactory {
// blabla...
}
fun setB() : ModelFactory {
// blabla...
}
fun setC() : ModelFactory {
// blabla...
}
fun build() : Model {
// An error occurs if any of setA, setB, and setC is not called.
}
}
//example
fun successTest() {
ModelFactory().setA().setB().setC().build() // No error occurs at compile time
}
fun failTest() {
ModelFactory().setA().build() // An error occurs at compile time because setB and setC are not called.
}
It's awkward grammatically, but I think it's been expressed what I want.
I have already implemented an error-raising runtime for this requirement, but I want to check this at compile time.
If possible, I think I should use annotations. But is this really possible at compile time?
With Kotlin, I have been avoiding builder pattern, as we can always specify default values for non-mandatory fields.
If you still want to use a builder pattern, you can use Step builder pattern that expects all mandatory fields to be set before creating the object. Note that each setter method returns the reference of next setter interface. You can have multiple Step builders based on the combination of mandatory fields.
class Model(val a: String = "", val b: String = "", val c: String = "")
class StepBuilder {
companion object {
fun builder(): AStep = Steps()
}
interface AStep {
fun setA(a: String): BStep
}
interface BStep {
fun setB(b: String): CStep
}
interface CStep {
fun setC(c: String): BuildStep
}
interface BuildStep {
//fun setOptionalField(x: String): BuildStep
fun build(): Model
}
class Steps : AStep, BStep, CStep, BuildStep {
private lateinit var a: String
private lateinit var b: String
private lateinit var c: String
override fun setA(a: String): BStep {
this.a = a
return this
}
override fun setB(b: String): CStep {
this.b = b
return this
}
override fun setC(c: String): BuildStep {
this.c = c
return this
}
override fun build() = Model(a, b , c)
}
}
fun main() {
// cannot build until you call all three setters
val model = StepBuilder.builder().setA("A").setB("B").setC("C").build()
}

Invoking methods on interfaces with generics

The following is a very simple illustration of what I'm trying to do:
interface Event {
fun value(): Int
}
class Event1: Event {
override fun value() = 1
}
class Event2: Event {
override fun value() = 2
}
interface EventConsumer<T> where T: Event {
fun consume(event: T)
}
class Event1Consumer: EventConsumer<Event1> {
override fun consume(event: Event1) {
println(event.value())
}
}
class Event2Consumer: EventConsumer<Event2> {
override fun consume(event: Event2) {
println(event.value())
}
}
class EventManager {
private val consumers: Map<KClass<*>, EventConsumer<*>> = mapOf(
Event1::class to Event1Consumer(),
Event2::class to Event2Consumer()
)
fun consume(event: Event) {
val consumer = consumers[event::class]
consumer?.consume(event)
}
}
The final method call (consumer.consume()) is giving me a compiler error
Out-projected type 'EventConsumer<*>?' prohibits the use of 'public
abstract fun consume(event: T): Unit defined in EventConsumer'
I know that Kotlin is a lot more strict about generics than Java which is probably why it doesn't work, but how would I implement something like this properly?
Since you are building the consumers map, it would be safe to make an unchecked cast to the correct generic EventConsumer type:
fun <T: Event> consume(event: T) {
val consumer = consumers[event::class] as? EventConsumer<T>
consumer?.consume(event)
}

Replacing SAM-constructor with lambda with covariant type

I have got the following Java interfaces:
interface Action1<T> {
void call(T t);
}
interface Test<T> {
void test(Action1<? super T> action)
}
And the following Kotlin class:
interface A {
fun go()
}
abstract class Main {
abstract fun a(): Test<out A>
fun main() {
a().test(Action1 { it.go() })
a().test { it.go() }
}
}
Now in the function main, the first statement compiles, but IntelliJ gives a warning that the SAM-constructor can be replaced with a lambda.
This would result in the second statement.
However, this second statement does not compile, because it has type Any?, not A. Removing the out modifier makes it compile again.
Why does this happen?
The use case of this is when the implementing class of Main needs to return Test<B> for the function a(), where B implements A:
class B : A {
override fun go() {
TODO()
}
}
class MainImp : Main() {
override fun a(): Test<out A> {
val value: Test<B> = object : Test<B> {
override fun test(action: Action1<in B>?) {
TODO()
}
};
return value
}
}
It is a compiler bug. You can track it here: https://youtrack.jetbrains.com/issue/KT-12238.