If a set of inner classes are the only implementations (subclasses) of their outer abstract containing class, how does one instantiate them?
abstract class A {
inner class A1 : A()
inner class A2 : A()
}
In other words, what is the syntax to construct an instance of A1 or A2?
EDIT: ... outside the body of class A.
Are you looking for this?
abstract class A {
fun doSome() { // OK
val a1 = A1()
val a2 = A2()
}
inner class A1 : A()
inner class A2 : A()
}
I think you probably want to construct instances of A1/A2 outside of A, like:
abstract class A {
inner class A1 : A()
inner class A2 : A()
}
fun doSome() { // Error
val a1 = A1()
val a2 = A2()
}
This is not allowed in both Kotlin and Java, because the inner class holds pointers to the outer class. If you want to construct A1/A2 outside of A, simply remove the inner modifiers.
abstract class A {
class A1 : A()
class A2 : A()
}
fun doSome() { // OK
val a1 = A.A1()
val a2 = A.A2()
}
Also, in addition, since you said it's
a set of inner classes are the only implementations (subclasses) of their outer abstract containing class
You can replace abstract modifier with sealed. This will help Kotlin do exhautiveness check in when expression.
Related
Why inner class in Kotlin can't not access extension function declared in outer class as below:
class A{
val a = "as".foo() // LINE 1
class B{
val b = "as".foo() // LINE 2
}
fun String.foo(){}
}
On LINE 1 extension function is resolved but on LINE 2 the function is not resolved. Wonder why there is such limitation?
This is not an inner class, because you didn't use the keyword inner on it. It is merely a nested class. If you're familiar with Java, it's like a static inner class. Since it is not inner, it does not have any implicit reference to the outer class, and cannot make bare calls to members of the outer class since there is no specific instance to use the members of. It can however call members of the outer class on an instance of the outer class, so you could for example do the following:
class A{
val a = "as".foo()
class B{
val b = A().run { "as".foo() }
}
fun String.foo(){}
}
Even though foo is an extension function, it's also a member of A because of where it's declared. Using a scope function that causes a class to be a receiver inside the scope is one way to call one of its member extension functions from another class.
EDIT: Here's an example of one reason you'd want to declare an extension inside a class.
class Sample(val id: Int) {
private val tag = "Sample#$id"
fun String.alsoLogged(): String{
Log.d(tag, this)
return this
}
}
You can use this extension to easily log Strings you're working with inside the class (or when it's the receiver of run or apply). It wouldn't make sense to declare outside the class because it uses the private tag property of that class.
It's because Kotlin compiles your code to
public final class A {
#NotNull
private final Unit a;
#NotNull
public final Unit getA() {
return this.a;
}
public final void foo(#NotNull String $this$foo) {
Intrinsics.checkNotNullParameter($this$foo, "$this$foo");
}
public A() {
this.foo("as");
this.a = Unit.INSTANCE;
}
public static final class B {
public B() {
// You can't access A's foo() method here.
}
}
}
data class Outer(val x: Int = 1, val predicate: Predicate<Int> = Inner()) {
private inner class Inner : Predicate<Int> {
override fun test(t: Int): Boolean = x == t
}
}
I get an error Constructor of inner class Inner can be called only with receiver of containing class where Inner() is called. Also if I do this.Inner() I get 'this' is not defined in this context.
I realise I can do:
data class Outer(val x:Int, val predicate: Predicate<Int> = Predicate<Int> { it == x }) {
}
but I want my Inner to be Seralizable so it cannot be an anonymous class.
inner classes are like non-static inner classes in Java, and you need an instance of Outer to create them. However, when specifying the default values of the constructor parameters, the instance of Outer that you are creating (aka this) has not been created yet, so you cannot do this.Inner().
For this scenario, you can remove inner, to make the Inner class more like a static inner class in Java. Add an Int constructor parameter to it so that you can pass the x from the outer to it:
data class Outer(val x: Int = 1, val predicate: Predicate<Int> = Inner(x)) {
private class Inner(val x: Int) : Predicate<Int> {
override fun test(t: Int): Boolean = x == t
}
}
I have the following interface and two classes:
interface A {
fun foo()
fun bar()
}
class B {
fun foo() {}
}
class C {
fun bar() {}
}
Is it possible to somehow provide implementation for this interface using/combining those 2 classes?
One way to do this without changing the given code is to just use instances of B and C in a new class implementing A:
class D : A {
private val b = B()
private val c = C()
override fun foo() = b.foo()
override fun bar() = c.bar()
}
This doesn't scale very well though, and requires to write boilerplate.
With Kotlin you can implement interfaces by delegation, which basically does exactly the above, but automatically.
However, this requires you to split your interface A into the part that is implemented by B and the part implemented by C:
interface Foo {
fun foo()
}
interface Bar {
fun bar()
}
interface A : Foo, Bar
class B : Foo {
override fun foo() {}
}
class C : Bar {
override fun bar() {}
}
class D : A, Foo by B(), Bar by C()
If you need configurable instances of B and C, you can pass them to D via its constructor:
class D(val b: B, val c: C): A, Foo by b, Bar by c
If B and/or C have constructors that take arguments, you can create instances of B and/or C using parameters from D's constructor:
class B(val something: String) : Foo { ... }
class D(something: String) : A, Foo by B(something), Bar by C()
You can create a new class that implements this interface and delegate method invocation to these classes.
class D(val b: B, val c: C) : A {
override fun foo() {
return b.foo()
}
override fun bar() {
return c.bar()
}
}
Or if you have access to interface A, you can change it next way
interface AB {
fun foo()
}
interface AC {
fun bar()
}
interface A : AB, AC
class B : AB {
override fun foo() {}
}
class C : AC {
override fun bar() {}
}
class D(val b: B, val c: C) : AB by b, AC by c, A
So, now, your D class implements interface A using delegates
There is 2 classes:
A - base class
B - class of member of A
with implementation something like this:
class A {
val b : B = B()
}
class B
Problem
Is it possible to create a binding for b to hide redundant info about b source in common classes?
Kodein declaration:
override val kodein by Kodein.lazy {
bind<A>() with singleton { A() }
bind<B>() with "a.b some impl???"
}
Usecase
class Usecase(kodein : Kodein){
val b : B = kodein.instance()
}
Very simple :
bind<B>() with provider { instance<A>().b }
The provider binding is the simplest one : it will call the provided function everytime.
The function itself runs inside a Kodein context, hence the use of the instance function.
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.)