How to implement an abstract getter with property - kotlin

I have java code:
public abstract class A {
abstract int getA()
}
I tried:
class B : A() {
val a = 0
}
Doesn't compile.
class B : A() {
override val a = 0
}
Still doesn't compile.
class B : A() {
override val a: Int get () = 1
}
Still doesn't compile.
class B : A() {
override val a: Int override get () = 1
}
Still doesn't compile.
class B : A() {
val a: Int override get () = 1
}
None of them are working. Does that mean I can only use
class B : A() {
override fun getA() = 1
}
? I think the last one(overriding the method) is ugly.
This could be worse when you have a getter-setter pair. It's expected to override getter-setter pair with a var property, but you have to write two methods.

According to #Miha_x64 ,
functions can be overriden only with a function.
Seems that I was trying something impossible.

Related

Kotlin parent logic to run after child's constructor

I got the following classes:
class B() : A {
override val p1: String = ...
override fun p2() : String { ... }
}
abstract class A() {
abstract val p1: String
abstract fun p2() : String
fun p3() : String = p1.plus("-").plus(p2())
init {
var p4 = p3()
}
}
I want p4 to be set at declaration. the issue is that when A() constructor is called p1 & p2() are not set yet, so p3() contains nulls. is there a way to solve it? like to run some logic after both constructors are called?
The function inheritance won't have any problem, as functions resolve statically.
Properties on the other hand, initialize after init block of super class has been executed.
You can simply fix this by moving the property p1 to the A's constructor instead, and add that to the constructor argument when extending the class:
class B : A(p1 = "...") { /* `p1 = ` is optional */
override fun p2(): String { return "asdf" }
}
abstract class A(val p1: String) {
abstract fun p2(): String
fun p3() : String = p1.plus("-").plus(p2())
init {
var p4 = p3()
println(p4) // prints: `...-asdf`
}
}
Easiest way is probably to just make it a lazy property that gets computed when it's first accessed (after construction)
abstract class A() {
abstract val p1: String
abstract fun p2() : String
fun p3() : String = p1.plus("-").plus(p2())
var p4: String by lazy { p3() }
}
If you actually want to use p4 in the init block though, i.e. you're doing something with it as part of the construction process, and you just want it to run after B has been constructed and initialised, I don't think there's any way around that. You might want to do some kind of getInstance approach instead
class B private constructor () : A() {
override val p1: String = "P1"
override fun p2() : String { return "P2" }
companion object {
fun newInstance() = B().apply{ initialise() }
}
}
abstract class A() {
abstract val p1: String
abstract fun p2() : String
fun p3() : String = p1.plus("-").plus(p2())
fun initialise() {
var p4 = p3()
print(p4)
}
}
but honestly the best way might just be to pass p1 and p2 into A as parameters, especially if it's a data class anyway

Is there a way to make sealed classes generics?

How a generic result or error type could be defined in Kotlin? Something like this example from TypeScript
type Errorneous<E, R> =
{ is_error: true, error: E } | { is_error: false, result: R }
function calculate(): Errorneous<String, Number> {
return { is_error: false, result: 2 }
}
The problem is that Kotlin doesn't have generic sealed classes.
It's possible to define something like
data class Errorneous<E, R>(val error: E?, val result: R?)
But it not ideal as it allows wrong usage like
Errorneous<String, Int>(null, null)
Errorneous<String, Int>("", 2)
UPDATE
Possible (not compiling) Kotlin code
sealed class Errorneous
class Success<R>(val result: R) : Errorneous()
class Fail<R>(val error: R) : Errorneous()
fun calculate(): Errorneous {
return Success(2)
}
fun main() {
val result = calculate()
if (result is Success<*>) {
val r: Int = result.result // <= Problem here, no smart cast
}
}
You have to add generic parameters to the base class as well:
sealed class Errorneous<E,R>
class Error<E,R>(val error: E): Errorneous<E,R>()
class Success<E,R>(val result: R): Errorneous<E,R>()
fun calculate(): Errorneous<String, Int> {
return Success(2)
}
fun main() {
val result = calculate()
if (result is Success<*, Int>) {
val r: Int = result.result // <= smart cast
}
}

Object expressions, Multiple supertype specification syntax?

I am new to Kotlin. I came across the Object Expressions section of https://kotlinlang.org
Some of the object expression syntaxes are very straight forward to understand,
Create an object of an anonymous class
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { ... }
override fun mouseEntered(e: MouseEvent) { ... }
})
Just an object
fun foo() {
val adHoc = object {
var x: Int = 0
var y: Int = 0
}
print(adHoc.x + adHoc.y)
}
But I am unable to understand the "Object expression with multiple supertypes specified" example given as below:
open class A(x: Int) {
public open val y: Int = x
}
interface B { ... }
val ab: A = object : A(1), B {
override val y = 15
}
What's happening here?
${ab.y} prints 15
but syntax -> ${ab.A.y} is not valid. My understanding of ${ab.A.y} it will print 1 :)
This line here:
val ab: A = object : A(1), B {
means that the class of ab is inherited from class A and implements interface B.
Actually the code example you gave will only compile if you declare and implement the interface. This is a possible implementation:
open class A(x: Int) {
public open val y: Int = x
}
interface B {
fun hi()
}
val ab: A = object : A(1), B {
override val y = 15
override fun hi() {
println("hi")
}
}
The expression ${ab.A.y} does not make much sense in this context, because the object ab does not have any field A. A is just the inherited superclass to which you could eventually cast.
It basically creates object ab with class type A with implementation of interface B.
So, let's say your class A has some method foo() & interface B has some method bar(), you can access them both on object ab as it's of class type A with implementation of B.
Hence, here you override variable y with value 15 meaning your superclass variable y will get overridden by value 15 from 1.

Kotlin: function delegation

I have a project that depends heavily on delegation and composition in Kotlin. Delegating properties is a breeze, but conceptually I'm not completely sure how to achieve delegation for functions in circumstances where the functions depend on other composed properties. I'd like to do something like this:
interface A {
val a: String
}
class AImpl: A {
override val a = "a"
}
interface B {
val b: String
}
class BImpl: B {
override val b = "b"
}
interface C<T> where T: A, T: B {
fun c() : String
}
class CImpl<T>(val ab: T) : C<T> where T: A, T: B {
override fun c() = ab.a + ab.b
}
// works
class ABC : A by AImpl(), B by BImpl()
// does not work
class ABC : A by AImpl(), B by BImpl(), C<ABC> by CImpl(this)
Of course, this type of thing would be achievable with the following:
interface A {
val a: String
}
class AImpl: A {
override val a = "a"
}
interface B {
val b: String
}
class BImpl: B {
override val b = "b"
}
interface C<T> where T: A, T: B {
fun c() : String
}
class CImpl<T>(val ab: T) : C<T> where T: A, T: B {
override fun c() = ab.a + ab.b
}
class AB : A by AImpl(), B by BImpl()
class ABC(ab: AB = AB(), c: C<AB> = CImpl<AB>(ab)) : A by ab, B by ab, C<AB> by c
but this feels clunky as it requires passing in objects for composition which bloats the size of the constructors - it would be cleaner for me to initialize the objects at the site of the class itself as they have no use outside of the class. Is there an elegant way to this with delegation and/or extensions?
You can make C extend A and B instead of passing to it a delegate. e.g.:
interface C : A, B {
fun c(): String
}
abstract class CImpl() : C {
abstract override val a: String
abstract override val b: String
override fun c(): String = a + b
}
class ABC : A by AImpl(), B by BImpl(), CImpl()
You can also do this with a default implementation in C without a CImpl:
interface C : A, B {
fun c(): String = a + b
}
class ABC : A by AImpl(), B by BImpl(), C
I don't think this is currently supported very well, but there's an issue that tracks this and related feature requests. (See Peter Niederwieser's comment on the issue.)

How to get kotlin function's caller

With this example:
open class Parent {
fun some():Parent {
return this;
}
}
class A : Parent(){
val name:String? = null;
}
But then this code results in an error:
val a = A().some().some()
a.name // ERROR
EDITOR NOTE: based on comments of the author to answers below, the question is NOT about referencing a.name but really is about something like "how do I get the instance of the class or its name that first started the chain of method calls". Read all comments below until the OP edits this for clarity.
my final goal is to return caller's type and can call this caller's instance property, no more as , no more override, any idea?
Just like java, you can use stackTrace's getMethodName(). Refer to the kotlin doc.
Actially your example is working(if you add open keyword because all classes in Kotlin are final by default:
A.kt
open class A {
fun some(): A {
return this
}
}
B.kt
class B : A() {
val test = "test"
}
And usage
val tmpB = (B().some().some() as B)
val test = tmpB.test
Edited:
It because function some() return parent class which doesn't have child class property. So you need to cast it to child class.(Update code)
open class Parent{
open fun foo(): Parent {
return this;
}
}
This is your Parent class. Parent class has a method named foo(). foo() is a method of class A which will return the instance of it's own class. We must have to open the class and method because by default their visibility modifier is final.
class A : Parent() {
override fun foo(): A { return this }
}
This is a class named A which extends Parent class. foo() is a method of class A which will return the instance of it's own class.
We will call it like this:
var a = A().foo().foo()
Your class always return Parent instance. This class do not have any field with the name name. To do that you have 2 ways:
The first:
open class Parent{
fun some():Parent{
return this
}
}
class A :Parent(){
val name:String? = null
}
fun main() {
val a = (A().some().some() as A)
a.name = "";
}
The second:
open class Parent{
open fun some():Parent{
return this
}
}
class A :Parent(){
override fun some():A {
return this
}
val name:String? = null
}
fun main() {
val a = A().some().some()
a.name = "";
}
i have know how to do this:
#Avijit Karmakar
#Trần Đức Tâm
use inline function
inline fun <reified T:Any> some(sql: String):T {
return this as T ;
}