Kotlin, instantiation issue and generic - kotlin

I have a class Vec3i that extends Vec3t
data class Vec3i(
override var x: Int = 0,
override var y: Int = 0,
override var z: Int = 0
) : Vec3t(x, y, z)
that has as one secondary constructor as follow
constructor(v: Vec3t<Number>) : this(v.x.toInt(), v.y.toInt(), v.z.toInt())
and another class Vec3ub that extends always Vec3t
data class Vec3ub(
override var x: Ubyte = Ubyte(0),
override var y: Ubyte = Ubyte(0),
override var z: Ubyte = Ubyte(0)
) : Vec3t(x, y, z)
Where Vec3t is in turn
abstract class Vec3t<T : Number>(
override var x: T,
override var y: T,
open var z: T
) : Vec2t(x, y)
And Ubyte extends Number
I'd like to instantiate a Vec3i from a Vec3ub
Vec3i(vec3ub)
but the compilers complains that there is no constructor for that..
why isn't valid the secondary constructor I quoted previously?

For completeness, as stated in my comment, the following compiles correctly:
data class Vec3i(
override var x: Int = 0,
override var y: Int = 0,
override var z: Int = 0
) : Vec3t<Int>(x, y, z) {
constructor(v: Vec3t<out Number>) : this(v.x.toInt(), v.y.toInt(), v.z.toInt())
}
data class Vec3ub(
override var x: Ubyte,
override var y: Ubyte,
override var z: Ubyte
) : Vec3t<Ubyte>(x, y, z)
abstract class Vec3t<T>(
override var x: T,
override var y: T,
open var z: T
) : Vec2t<T>(x, y)
open class Vec2t<T>(
open var x: T,
open var y: T
)
fun test(vec3ub: Vec3ub) {
val vec3i = Vec3i(vec3ub)
}
abstract class Ubyte : Number()
Note the constructor(v : Vec3t<out Number>) : ... and all other added generic parameter types. Vec3t<out Number> is necessary instead of just Vec3t<Number> here since you don't pass a Number, but rather a subclass of it.

Related

Using abstract with Binary Search in Kotlin

I have a task in kotlin to use an abstract class, and the example was about binary search
so it shows an error message in the run.
first class is non
first class there's a non abstract class but it a parent class
second an abstract class the inherite the parent classes
third a class that display the operation
and that's my code:
open class BinarySearch() {
fun BinarySearchFunction(arr: Array<Int>, l: Int, r: Int, x: Int): Int {
if(r >= 1) {
var mid:Int=1+(r-1)/2
if (arr[mid] == x) {
return mid
}
if(arr[mid] > x){
return BinarySearchFunction(arr,l,mid-1,x)
}
return BinarySearchFunction(arr,mid+1,r,x)
}
return -1
}
open fun displayMassage(Massage:String){}
}
abstract class print(): BinarySearch() {
fun Function() {
var obj = BinarySearch()
var a = arrayOf<Int>(2, 3, 4, 10, 40)
var n = a.size
var x = 10
var result = obj.BinarySearchFunction(a, 0, n - 1, x)
if(result == -1)
println("Element not present")
else
println("Element found at index $result")
}
}
class display():print(){
override fun displayMassage(massage:String){
println(massage)
}
}
fun main() {
var dis=display()
dis.displayMassage("The Binary Search : ")
dis.Function()
}
You have an error in the implementation of the algorithm causing it to do infinite recursion.
I believe
var mid: Int = 1 + (r - 1) / 2
actually needs to be
var mid: Int = l + (r - 1) / 2

Best way to hide internal classes by interfaces

what is the best way to hide an impl class behind an interface?
The companion creator works well, but needs to repeat all the arguments of the constructor twice.
Is there a way to simplify A.from(x,y,z,a,b,c,d) = AImpl(x,y,z,...)?
//the application will only see this interface
interface A {
val x: X
val y: Y
companion object {
//choose any implementation without breaking existing code
#JvmStatic
fun from(x: X, y: Y): A = AImpl(x = x, y = y) //inconvenient for many arguments
}
}
internal class AImpl(
override val x: X,
override val y: Y
) : A
fun someApplication() {
val a = A.from(..., ...) //no reference to AImpl
//use a: A
}
Thank you very much.
Martin
The way you wrote it is already good. If you're concerned about too many parameters, note that you don't have to name and pass every single one of them, and not every property needs to be passed as a constructor parameter. Depending on the implementation class, some properties can be defaulted or calculated:
interface A {
val x: X
val y: Y
companion object {
fun from(x: X, y: Y): A = AImpl(x)
}
}
internal class AImpl(
override val x: X,
) : A {
override val y = something()
}
Furthermore, AImpl doesn't have to be internal; it can be private or even an anonymous class, if it's a very short one (otherwise the code can become unreadable):
interface A {
val x: X
val y: Y
companion object {
fun from(x: X, y: Y): A = object : A {
override val x = x
override val y = y
}
}
}
Instead of using a member function of a companion object, a common Kotlin-idiomatic way is to use a standalone factory function with the same name as the interface:
fun A(x: X, y: Y): A = AImpl(x, y)
An example of such a function is MutableList: it has the same name as interface MutableList, and it happens to return an ArrayList but that's just implementation detail: it's only documented to return something that implements interface MutableList.
I don't really understand what are you tring to do.
So i'm not sure if this will be the answer to your question.
fun main() {
val x = X()
val y = Y()
val a = AImpl().from(x,y)
a.x.toString()
a.y.toString()
//use object class so you can use the class without ()
val b = BImpl.from(x,y)
b.x.toString()
b.y.toString()
}
class X{}
class Y{}
interface A
{
val x : X
val y : Y
fun from(xValue : X, yValue : Y) : A
}
internal class AImpl() : A {
override var x : X = X()
override var y : Y = Y()
override fun from(xValue : X, yValue : Y) : A {
x = xValue
y = yValue
return this
}
}
object BImpl : A {
override var x : X = X()
override var y : Y = Y()
override fun from(xValue : X, yValue : Y) : A {
x = xValue
y = yValue
return this
}
}
I don't think you should implementation anything in Interface
but If you want your code to work
companion object {
//choose any implementation without breaking existing code
#JvmStatic
//fun from(x: X, y: Y): A = AImpl(x = x, y = y)
//because you Return A That's why you got no reference to AImpl
//so don't return A but make it AImpl directly
//but it's still act like "A" interface.
fun from(x: X, y: Y) = AImpl(x,y)
}
}

Kotlin how to copy class property fields in its own member function

I have the following code, I would like to update the properties in class A, in c++, I can use something like this = A() within the udpate() that invokes implicity operator = ()
data class B(
var A: Int = 10,
var B: Long = 20L,
var C: Double = 200.0
)
data class A(
var a: Int = 0,
var b: Long = 0L
) {
fun badUpdate(input: B) {
var holder = this#A // It does not work, any better way to update within the member function?
holder = A(input.A, input.B)
}
fun aboriginalUpdate(input:B) {
a = input.A // It works, but what if I have 30 properties?
b = input.B
}
fun update(input: B) : A {
return A(input.A, input.B) // Works but not ideal, the return value is not necessary
}
}
fun main() {
var data0 = A()
val data = B(A = 300)
data0.badUpdate(data) // data0.a does not change (nothing invoked in update0)
data0 = data0.update(data)
println("$data0")
}
Any better way to update the properties within the class A?
I thnk 'apply()' is what you are looking for:
data class B(
var a: Int = 10,
var b: Long = 20L,
var c: Double = 200.0
)
data class A(
var a: Int = 0,
var b: Long = 0L
) {
fun goodUpdate(input: B) {
this.apply {
a = input.a
b = input.b
}
}
}
fun main() {
var data0 = A()
val data = B(a = 300)
data0.goodUpdate(data)
println("$data0") // A(a=300, b=20)
}
but unlike in the example you provided from C, you are not creating a new instance, you are updating properties of the existing one, which I believe you wanted
but you can achieve that even simpler, by reassigning object fields:
fun betterUpdate(input: B) {
this.a = input.a
this.b = input.b
}

Kotlin - Can't assign new values to lateinit vars via Destructuring Declaration

The following Kotlin code works
val (x, y) = getSomeXYPair()
But you can't do this with lateinit global vars
class Foo {
private lateinit var x: Int
private lateinit var y: Int
init {
(x, y) = getSomeXYPair()
}
}
I'm just wondering if I'm either doing something wrong, or this just isn't supported in Kotlin?
You can't do it with any type of variables, local or not:
fun main() {
var x : Int = 1
var y : Int = 2
(x, y) = getSomeXYPair()
}
This syntax is simply invalid in Kotlin. You're required to start destructuring declaration with either var or val:
https://kotlinlang.org/docs/reference/multi-declarations.html#destructuring-declarations
That is, putting aside the fact that lateinit is not supported on primitive types such as Int.

How do I bind a custom property to a textfield bidirectionally?

I have a complex object that I want to display in a textfield. This is working fine with a stringBinding. But I don't know how to make it two-way so that the textfield is editable.
package com.example.demo.view
import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty
import tornadofx.*
class MainView : View("Hello TornadoFX") {
val complexThing: Int = 1
val complexProperty = SimpleObjectProperty<Int>(complexThing)
val complexString = complexProperty.stringBinding { complexProperty.toString() }
val plainString = "asdf"
val plainProperty = SimpleStringProperty(plainString)
override val root = vbox {
textfield(complexString)
label(plainProperty)
textfield(plainProperty)
}
}
When I run this, the plainString is editable and I see the label change because the edits are going back into the property.
How can I write a custom handler or what class do I need to use to make the stringBinding be read and write? I looked through a lot of the Property and binding documentation but did not see anything obvious.
Ta-Da
class Point(val x: Int, val y: Int) //You can put properties in constructor
class PointConverter: StringConverter<Point?>() {
override fun fromString(string: String?): Point? {
if(string.isNullOrBlank()) return null //Empty strings aren't valid
val xy = string.split(",", limit = 2) //Only using 2 coordinate values so max is 2
if(xy.size < 2) return null //Min values is also 2
val x = xy[0].trim().toIntOrNull() //Trim white space, try to convert
val y = xy[1].trim().toIntOrNull()
return if(x == null || y == null) null //If either conversion fails, count as invalid
else Point(x, y)
}
override fun toString(point: Point?): String {
return "${point?.x},${point?.y}"
}
}
class MainView : View("Hello TornadoFX") {
val point = Point(5, 6) //Probably doesn't need to be its own member
val pointProperty = SimpleObjectProperty<Point>(point)
val pc = PointConverter()
override val root = vbox {
label(pointProperty, converter = pc) //Avoid extra properties, put converter in construction
textfield(pointProperty, pc)
}
}
I made edits to your converter to "account" for invalid input by just returning null. This is just a simple band-aid solution that doesn't enforce correct input, but it does refuse to put bad values in your property.
This can probably be done more cleanly. I bet there is a way around the extra property. The example is fragile because it doesn't do input checking in the interest of keeping it simple. But it works to demonstrate the solution:
class Point(x: Int, y: Int) {
val x: Int = x
val y: Int = y
}
class PointConverter: StringConverter<Point?>() {
override fun fromString(string: String?): Point? {
val xy = string?.split(",")
return Point(xy[0].toInt(), xy[1].toInt())
}
override fun toString(point: Point?): String {
return "${point?.x},${point?.y}"
}
}
class MainView : View("Hello TornadoFX") {
val point = Point(5, 6)
val pointProperty = SimpleObjectProperty<Point>(point)
val pointDisplayProperty = SimpleStringProperty()
val pointStringProperty = SimpleStringProperty()
val pc = PointConverter()
init {
pointDisplayProperty.set(pc.toString(pointProperty.value))
pointStringProperty.set(pc.toString(pointProperty.value))
pointStringProperty.addListener { observable, oldValue, newValue ->
pointProperty.set(pc.fromString(newValue))
pointDisplayProperty.set(pc.toString(pointProperty.value))
}
}
override val root = vbox {
label(pointDisplayProperty)
textfield(pointStringProperty)
}
}