Useless Kotlin delegate - kotlin

I'm trying to understand why we have feature as delegate in Kotlin.
This example is similar to wiki example https://en.wikipedia.org/wiki/Delegation_pattern
Check this commented fragment, I don't need it for using area function on bounds so why we should use : ClosedShape by bounds ?
interface ClosedShape {
fun area(): Int
}
class Rectangle(val width: Int, val height: Int) : ClosedShape {
override fun area() = width * height
}
class Window(private val bounds: ClosedShape) /*: ClosedShape by bounds */ {
init {
bounds.area()
}
}

I don't need it for using area function on bounds
The point is not about whether you can use area on bounds or not. Sure, if all you want to do is to call bounds.area(), you don't need : ClosedShape by bounds.
Here's a little hypothetical situation, based on ClosedShape and Window, where using the by syntax to implement an interface is helpful.
Notice how a Window is bounded by a Rectangle. Wouldn't it make sense for Window to also be a ClosedShape? If we have a function that works on ClosedShape, wouldn't it be nice if we can directly pass a Window to it, rather than passing window.bounds?
fun printArea(shape: ClosedShape) {
println(shape.area())
}
// we could write this:
printArea(window)
// rather than:
printArea(window.bounds)
This would mean that Window would implement ClosedShape. We could implement it without using a delegate:
class Window(private val bounds: ClosedShape) : ClosedShape {
override fun area() = bounds.area()
}
But that would be very tedious if ClosedShape had many more methods than area. Imagine having to implement 20 methods, all of which just calls that same method on bounds:
class Window(private val bounds: ClosedShape) : ClosedShape {
override fun area() = bounds.area()
override fun perimeter() = bounds.perimeter()
override fun numberOfSides() = bounds.numberOfSides()
override fun isConcave() = bounds.isConcave()
override fun contains(point: Point) = bounds.contains(point)
override fun methodWithALotOfParameters(x: Int, y: String, z: Boolean) = bounds.methodWithALotOfParameters(x, y, z)
override fun color() = bounds.color()
// and so on...
}
You can also imagine how horrible this would get, if the delegate isn't as short as bounds, but something like bounds.someProperty.anotherProperty.
The by syntax eliminates all that tedious work, letting you just write:
class Window(private val bounds: ClosedShape) : ClosedShape by bounds
And that's it! You can now use any Window as a ClosedShape.

Related

What are the real benefits of using delegation instead of inheritance [duplicate]

I'm trying to understand why we have feature as delegate in Kotlin.
This example is similar to wiki example https://en.wikipedia.org/wiki/Delegation_pattern
Check this commented fragment, I don't need it for using area function on bounds so why we should use : ClosedShape by bounds ?
interface ClosedShape {
fun area(): Int
}
class Rectangle(val width: Int, val height: Int) : ClosedShape {
override fun area() = width * height
}
class Window(private val bounds: ClosedShape) /*: ClosedShape by bounds */ {
init {
bounds.area()
}
}
I don't need it for using area function on bounds
The point is not about whether you can use area on bounds or not. Sure, if all you want to do is to call bounds.area(), you don't need : ClosedShape by bounds.
Here's a little hypothetical situation, based on ClosedShape and Window, where using the by syntax to implement an interface is helpful.
Notice how a Window is bounded by a Rectangle. Wouldn't it make sense for Window to also be a ClosedShape? If we have a function that works on ClosedShape, wouldn't it be nice if we can directly pass a Window to it, rather than passing window.bounds?
fun printArea(shape: ClosedShape) {
println(shape.area())
}
// we could write this:
printArea(window)
// rather than:
printArea(window.bounds)
This would mean that Window would implement ClosedShape. We could implement it without using a delegate:
class Window(private val bounds: ClosedShape) : ClosedShape {
override fun area() = bounds.area()
}
But that would be very tedious if ClosedShape had many more methods than area. Imagine having to implement 20 methods, all of which just calls that same method on bounds:
class Window(private val bounds: ClosedShape) : ClosedShape {
override fun area() = bounds.area()
override fun perimeter() = bounds.perimeter()
override fun numberOfSides() = bounds.numberOfSides()
override fun isConcave() = bounds.isConcave()
override fun contains(point: Point) = bounds.contains(point)
override fun methodWithALotOfParameters(x: Int, y: String, z: Boolean) = bounds.methodWithALotOfParameters(x, y, z)
override fun color() = bounds.color()
// and so on...
}
You can also imagine how horrible this would get, if the delegate isn't as short as bounds, but something like bounds.someProperty.anotherProperty.
The by syntax eliminates all that tedious work, letting you just write:
class Window(private val bounds: ClosedShape) : ClosedShape by bounds
And that's it! You can now use any Window as a ClosedShape.

Kotlin adapter pattern: Duplicate method name error on getter function

Just simple kotlin code to demo Adapter Pattern in Gang of Four Design Pattern. I have a presentation today about this but i can't done it. So sad. I don't want to add much details but they don't allow me to post without much details.
Exception:
Exception in thread "main" java.lang.ClassFormatError: Duplicate method name "getRadius" with signature "()I" in class file RoundHole
at java.lang.ClassLoader.defineClass1 (ClassLoader.java:-2)
at java.lang.ClassLoader.defineClass (ClassLoader.java:756)
at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:142)
Code:
interface WorkingWithRound {
fun getRadius(): Int
}
open class RoundPeg(val radius: Int = 0): WorkingWithRound {
override fun getRadius() = radius
}
class RoundHole(val radius: Int = 0): WorkingWithRound {
override fun getRadius() = radius
fun fit(peg: RoundPeg) {
println(getRadius() >= peg.getRadius())
}
}
class SquarePeg(val width: Int = 0)
class SquarePegAdapter(val speg: SquarePeg): RoundPeg() {
override fun getRadius() = (speg.width / 2 * 1.4).toInt()
}
fun main() {
val hole = RoundHole(5)
val rpeg = RoundPeg(5)
hole.fit(rpeg)
val small_sqpeg = SquarePeg(5)
val large_sqpeg = SquarePeg(10)
//hole.fit(small_sqpeg) // this won't compile (incompatible types)
val small_sqpeg_adapter = SquarePegAdapter(small_sqpeg)
val large_sqpeg_adapter = SquarePegAdapter(large_sqpeg)
hole.fit(small_sqpeg_adapter) // true
hole.fit(large_sqpeg_adapter) // false
}
Kotlin generates getter method for instance variables, hence the error. Couple of options to fix the issue
Make radius variable private
open class RoundPeg(private val radius: Int = 0): WorkingWithRound
Mark radius with #JvmField to instruct compiler not to generate any getter
class RoundHole(#JvmField val radius: Int = 0): WorkingWithRound
I think this would be simpler (as well as avoiding the compilation problems) if the interface defined a property, rather than a getter method:
interface WorkingWithRound {
val radius: Int
}
That compiles down to pretty much the same bytecode; but the intent is clearer, and it can then be implemented directly in the constructors:
open class RoundPeg(override val radius: Int = 0): WorkingWithRound
class RoundHole(override val radius: Int = 0): WorkingWithRound {
fun fit(peg: RoundPeg) {
println(radius >= peg.radius)
}
}
The SquarePegAdapter can be simplified, as it no longer needs to store the speg value, but can simply use it as an initialiser for the property:
class SquarePegAdapter(speg: SquarePeg): RoundPeg() {
override val radius = (speg.width / 2 * 1.4).toInt()
}
And the rest of the code needs no changes.

How can I enforce that a class has a companion object?

What I want is this:
interface base {
abstract static fun foo()
}
class impl : base {
override static fun foo()
}
Normally, Kotlin solves problems using companion objects rather than static functions. But an interface can't define a requirement for a companion object with function. So how can I accomplish this? The code that uses this would look like
fun <T : base> bar() {
T.foo()
}
Any other way to get this behavior? Namely, that I can execute a function of a derivative of T, without knowing the specific type, and not assuming the derivative has a default constructor?
Edit
I was able to get this to do what I want by using value parameters of types that can be set on the companion objects of the classes I want to work with. An illustrative example of what I want to use this technique for.
import kotlin.reflect.full.*
interface DynamicBuilder {
fun build(sides: Int): Shape?
}
interface Shape {
companion object : DynamicBuilder {
override fun build(sides: Int) = null
}
}
abstract class Shape2D : Shape {
companion object : DynamicBuilder {
override fun build(sides: Int) = if(sides > 0) Square() else Circle()
}
}
abstract class Shape3D : Shape {
companion object : DynamicBuilder {
override fun build(sides: Int) = if(sides > 0) Cube() else Sphere()
}
}
class Square : Shape2D()
class Circle : Shape2D()
class Sphere : Shape3D()
class Cube : Shape3D()
fun Build(sides: Int, builder: DynamicBuilder): Shape? {
return builder.build(sides)
}
inline fun <reified T : Shape> Build(sides: Int): Shape? {
return Build(sides, T::class.companionObjectInstance as DynamicBuilder)
}
fun main() {
println(Build(0, Shape2D))
println(Build(4, Shape2D))
println(Build<Shape3D>(0))
println(Build<Shape3D>(6))
}
The goal is that I can create a new entire class of Shape, and have all the logic related to how it builds the concrete object contained in that file, rather than having some monolithic shared switch statement.
An interface can define a requirement for some object with function, and you can suggest it to be the companion object even if you can't force it to be.
interface BaseCompanion {
fun foo(): Unit
}
interface Base {
companion object : BaseCompanion {
fun foo() { println("in Base") }
}
fun companion(): BaseCompanion = Base
}
interface Derived : Base {
companion object : BaseCompanion {
fun foo() { println("in Derived") }
}
override fun companion() = Derived
}
// value parameter, not type parameter
fun bar(companion: BaseCompanion) {
companion.foo()
}
bar(Base)
bar(Derived)
The companion() function isn't actually used in this case, it's for when you want to access the companion from a Base instance:
fun baz(x: Base) {
x.companion().foo()
}
Another (unsafe) option is to define companion() using reflection.
fun companion() = this::class.companionObjectInstance as BaseCompanion
Plus: no need to explicitly override it in Derived; minuses: 1. will crash at runtime if you forget to create the companion or to extend BaseCompanion; 2. slower than non-reflection definition.
TL;TR:
How can I enforce that a class has a companion object?
You cannot.
Kotlin has no static methods. Even if it had them, they wouldn't be overridable, as they are not in Java. The same holds for companion objects. Kotlin code is eventually compiled to Java byte code, so what is not possible in Java won't be possible in Kotlin either.
Edit:
It's interesting to see what the compiler has to say about it. Consider the following snippet:
open class Base {
companion object {
fun test() {}
}
}
inline fun <reified T : Base> staticCall() {
T.test() // <-- ERROR
}
The error message:
Type parameter 'T' cannot have or inherit a companion object, so it cannot be on the left hand side of dot
Based on your updated question, it seems like what you want is usually achieved using the factory pattern. Alternatively you could also use dependency injection. There are many options without the usage of reflection.
Why shouldn't you use reflection?
There are a few reasons here and here and you can find more if you google it. Generally reflection was created for a specific purpose, to discover the functionality of a class that was unknown at compile time. You do not use it for this purpose, since your implementation requires you to know the class, in order to pass it as a reified generic parameter. If you do require to discover classes that you don't know at compile time, you can use dependency injection.
The simpler solution for your version is a factory pattern:
interface Shape
class Square : Shape
class Circle : Shape
class Sphere : Shape
class Cube : Shape
object ShapeFactory {
fun build2DShape(sides: Int): Shape {
if(sides > 0) Square() else Circle()
}
fun build3DShape(sides: Int): Shape {
if(sides > 0) Cube() else Sphere()
}
}
fun main() {
println(ShapeFactory.build2DShape(0))
println(ShapeFactory.build3DShape(0))
}
In short, Build<Shape3D>(0) is replaced by ShapeFactory.build3DShape(0). The caller still has to know that there are 3DShapes and where they are. The only thing that changed is that you do not require Reflection.
This requires the person calling the function to know of the existence of 2D and 3D shapes. Same as in your implementation with reflection. This way you can have all the logic how to create the shapes in the same file as the shapes. You could even make the factory call some functions in the companion object of the shape if you wish to do so. Your factory knows of the existence of those subclasses. But since you can put the factory in the same file as the subclasses, that doesn't split the logic to somewhere else.
If you want to delegate the deciding whether it is a 2D or a 3D shape to a subclass you can do the following:
interface Shape
class Square : Shape
class Circle : Shape
class Sphere : Shape
class Cube : Shape
object ShapeFactory {
fun build2DShape(sides: Int): Shape {
return if(sides > 0) Square() else Circle()
}
fun build3DShape(sides: Int): Shape {
return if(sides > 0) Cube() else Sphere()
}
}
fun getBuilder(dimensions: Int): (sides: Int) -> Shape {
if (dimensions == 2)
return ShapeFactory::build2DShape
else
return ShapeFactory::build3DShape
}
fun main() {
print (getBuilder(2)(3))
}

When should I use delegation in Kotlin?

I have been going through multiple links (One, Two) and documentation regarding the delegate pattern and somewhat understand the advantage it brings in the form of "composition over inheritance". I can see how the inbuilt delegate properties (lazy, vetoable, map, observable) are useful; but having a hard time understanding 2 areas:
1. Why/When should I write a custom delegate for property? How is it better than overriding getter/setter of that property?
Comparing the 2 approaches:
private var withoutDelegate: String = ""
get() = DataHelper.getLatestData(::withoutDelegate.name)
set(value) {
DataHelper.setLatestData(value)
field = value
}
val withDelegate by StringDelegateProvider()
class StringDelegateProvider {
operator fun getValue(thisRef: String?, property: KProperty<*>): String {
return DataHelper.getLatestData(property.name)
}
}
2. At the class level, how is delegation better than traditional composition patterns?
Comparing the 2 approaches - composition without delegation seems much more concise:
interface Base {
fun print()
}
class BaseImpl1(val x: Int) : Base {
override fun print() { print(x) }
}
class BaseImpl2(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
fun clientFunctionWithDelegation() {
val i1 = BaseImpl1(10)
val i2 = BaseImpl2(10)
val b1 = Derived(i1)
val b2 = Derived(i2)
b1.print()
b2.print()
}
fun clientFunctionWithoutDelegation(){
//wihtout extending Base, we can still create multiple types of Base and use them conditionally.
val i1: Base = BaseImpl1(10)
val i2: Base = BaseImpl2(10)
i1.print()
i2.print()
}
Would appreciate if the community can share some use-cases where delegation can help.
1: You can reuse the delegate without having to override get and/or set each time. Example: the lazy delegate
2: let's say you want to create a MutableList that prints the list every time you mutate the list. You don't want to reimplement MutableList, you just want to override the functions mutating the list. So instead of manually delegating every call, you just say class PrintList<T>(original: MutableList<T>) by original and you just override the functions you care about

Is there a standard Kotlin way to make just this one special-case object of a data class have a different toString() method?

Here's my attempt:
data class LineStyle(val thickness: Float) {
override fun toString() =
if (thickness == 0f) {
"NO_LINE"
} else {
"LineStyle(${thickness}f)"
}
companion object {
#JvmField
val NO_LINE = LineStyle(0f)
}
}
I'd rather override toString separately for the NO_LINE singleton, but don't see how. I have a lot of classes that have a zero instance.
There are a few different ways you could do this. You could use a sealed or open class as your actual LineStyle and have the NoLine as a companion object, forcing you to refer to it as LineStyle.NoLine. In that object, you could override the actual toString() method with whatever you want. The implementation would look something like this:
// sealed so it's easier to deal with in when statements
sealed class LineStyle(val thickness: Float) {
// defines a no line style
companion object NoLine: LineStyle(0f) {
override fun toString() = "NO_LINE"
}
}
fun main(args: Array<String>) {
// only able to access it as
LineStyle.NoLine
}
However, with this approach, you lose the data aspect of the class. The only other option is to do basically what you have done, instead, maybe use a when statement though for future extensibility. It's not the prettiest but it works:
data class LineStyle(val thickness: Float) {
// if you want extensibility, you could use a when statement
override fun toString() = if(this == NO_LINE) "NO_LINE" else super.toString()
companion object {
val NO_LINE = LineStyle(0f)
}
}