What are the real benefits of using delegation instead of inheritance [duplicate] - 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

Useless Kotlin delegate

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.

Is there any way in Kotlin to add a custom function to a property inside an interface?

Ultimately what I would like to do is have a class with a field inside of it that I can call a function on. I have tried extensions functions but that only extends the class definition that the field is defined as. I tried to do it in an interface but ended up with a standard function call.
so,
private interface Geometric{
var position: Float3
get() { return position }
set(value) {
this.dirty = true
this.position = value
}
fun TransformationMatrix() =
floatArrayOf(1f, 0f, 0f, 0f,
0f, 1f, 0f, 0f,
0f, 0f, 1f, 0f,
this.position.x, this.position.y, this.position.z, 1f)
which allows me to do
val translationMatrix = myobject.TransformationMatrix()
but what I really want to do is
val translationMatrix = myobject.position.toTransformationMatrix()
I know I could write a class called position that inherits from float3 but my object class is really the only class that will be using it
data class Object(val objectName: String, val meshName : String,
override var position : Float3 = Float3(0f,0f,0f),
override var rotation: Quaternion = Quaternion(0f,0f,0f, 1f),
override var scale: Float3 = Float3(1f,1f,1f)
) : Geometric, OpenGLObject, GameObject/*Color*/
As you can see I wrote a special class for Quaternion because it has a secondary constructor that takes Euler angles otherwise I would also want this to just be a Float4 with a function on rotation that returns the float4 backing field as a rotation matrix.
basically, the idea here is to keep the data class as light as possible and then just ask for the data it holds in the formate I need. position.toMatrix4(), rotation.toMatrix(), ext.
Is there a way I can use objects or some other cool Kotlin things to achieve this?
I think you are in luck. there is a new experimental Future in kotlin called inline class which I think is exactly what you need.
inline class is used as a wrapper around a type!
inline class Position(val pos: Float3 ) {
fun transformationMatrix() = ...
}
and you can use it like
val pos = Position(f3)
pos.transformationMatrix()
and you don't need to worry about not reusing it or any overheads because in runtime variable pos converts to only f3 and its type would be Float3 and there will be no sign of the class.
and please don't start your function names with uppercase letters!!

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)
}
}