How to provide the base class in Koin? - kotlin

For example I the following classes:
abstract class BaseClass()
class SpecificClass : BaseClass()
Now, I want to provide SpecificClass through koin dependency inject but I also want to provide the base class BaseClass in the same graph.
To be clear I want to do something like:
class Someclass {
...
private specificClass: SpecificClass by inject()
...
}
class Someclass {
...
private baseClass: BaseClass by inject()
// where this BaseClass is just the the same instace of the SpecificClass in the dependency graph
...
}
How do I do my module to do this? How can I inject the implementation instance to the baseClass reference?

You can do it using Koin in 2 ways
Methodn 1
You can create dependencies for both of them like this
single {
SpecificClass()
}
single<BaseClass> {
get<SpecificClass>()
}
In this way, whenever you inject an instance, it will get injected accordingly
Method 2
You can make use of named dependencies like this
single("BaseClassImpl") {
SpecificClass()
}
And when you want to inject it, provide key for that dependency like this:
class Someclass {
...
private specificClass: SpecificClass by inject("BaseClassImpl")
...
}
class Someclass {
...
private baseClass: BaseClass by inject("BaseClassImpl")
// where this BaseClass is just the the same instace of the SpecificClass in the dependency graph
...
}

You can't inject abstract classes.
In order to inject a class, it must be instantiable and abstract classes are not.
To inject SpecificClass with Koin you need to create a module:
val appModule = module {
single {
SpecificClass()
}
}
Initialize it in your application class:
class MyApplication : Application() {
override fun onCreate(){
super.onCreate()
// start Koin!
startKoin {
// declare used Android context
androidContext(this#MyApplication)
// declare modules
modules(appModule)
}
}
}
And use the inject delegation in your activity/fragment
class MyActivity() : AppCompatActivity() {
val specificClass : SpecificClass by inject()
}

Related

in kotlin, how to access protected static member in parent class from sub class

It is code worked in java but after convert to kotlin it does not compile.
Having a base class which has some defines as static protected member in the companion object:
abstract class ParentClass {
companion object {
#JvmField
final protected val SERVICE_TYPE_A = "the_service_type_a"
}
}
and the child class:
class ChildClass: ParentClass {
public override fun getServiceType(): String {
return SERVICE_TYPE_A. //<== got compile error
}
}
it does not compile.
how to access a parent class static protected member from subclass?
You need to use #JvmStatic instead as follows:
abstract class ParentClass {
companion object {
#JvmStatic
protected val SERVICE_TYPE_A = "the_service_type_a"
}
abstract fun getServiceType(): String
}
The final keyword in SERVICE_TYPE_A is redundant since everything is final by default in Kotlin. This also mean that if you want ParentClass to be extended, then you need to explicitly define it as open.
Then your ChildClass would look as follows:
class ChildClass: ParentClass() {
override fun getServiceType(): String {
return SERVICE_TYPE_A
}
}

Kotlin Generic class using inheritance

I have a BaseClass and several ChildClasses. I BaseClass has a doSomething() function, which I have to override. I cannot change BaseClass or any ChildClass.
class BaseClass {
fun doSomething() {}
}
class ChildClass1 : BaseClass {}
class ChildClass2 : BaseClass {}
The overridden doSomething() function of the ChildClass have to do the same thing. So I could do this:
class MyChildClass1 : ChildClass1 {
override doSomething() {
// some tasks
}
}
class MyChildClass2 : ChildClass2 {
override doSomething() {
// same tasks as in ChildClass1
}
}
Obviously, I dont want boilerplate code. I thought about Kotlin Generics where I define on class and depending on which ChildClass I pass in, it overrides the doSomething() function.
The context is actually a little bit more complex, so I cant just pass a lambda or something like that.
Here some pseudo code, what I try to achieve:
class GenericClass : <T: BaseClass> {
override doSomething() {
// tasks ...
}
}
var genericChildClass1 = GenericClass<ChildClass1>()
Is this somehow possible in Kotlin?
Thanks!

override function with concrete type parameter

Hi I would like know why the following example doesn't work
abstract class BaseClass {
}
class ConcretClasOne : BaseCalculator {
}
class ConcretClasTwo : BaseCalculator {
}
abstract class BaseRun {
abstract fun run(param: BaseClass): Int
}
class ConcretRun : BaseRun {
override fun run(param: ConcretClasOne): Int {
return 0
}
}
this shows me a message run overrides nothing.
I suppose that kotlin isn't able to match the abstract class and the concrete implementation, but what other alternative is there to emulate this behavior, that the run method in the concrete class ConcretRun should receive a concrete param ConcretClasOne?
Generics
Using generics, you can make the base class have a type extending the base class, so that the run method can take that type in.
abstract class BaseClass {
}
class ConcretClasOne: BaseCalculator {
}
class ConcretClasTwo: BaseCalculator {
}
abstract class BaseRun<T: BaseClass> {
abstract fun run(param: T): Int
}
class ConcretRun: BaseRun<ConcretClasOne> {
override fun run(param: ConcretClasOne): Int {
return 0
}
}
Why your code doesn't work
At the moment you are trying to override a method with a more specific type, but as the more general base method can accept more types the more specific method cannot override it.

What is the difference between 'open' and 'public' in Kotlin?

I am new to Kotlin and I am confused between open and public keywords. Could anyone please tell me the difference between those keywords?
The open keyword means “open for extension“ - i.e. it's possible to create subclasses of an open class:
The open annotation on a class is the opposite of Java's final: it allows others to inherit from this class. By default, all classes in Kotlin are final, which corresponds to Effective Java, Item 17: Design and document for inheritance or else prohibit it.
You also need to be explicit about methods you want to make overridable, also marked with open:
open class Base {
open fun v() {}
fun nv() {}
}
The public keyword acts as a visibility modifier that can be applied on classes, functions, member functions, etc. If a top-level class or function is public, it means it can be used from other files, including from other modules. Note that public is the default if nothing else is specified explicitly:
If you do not specify any visibility modifier, public is used by default, which means that your declarations will be visible everywhere
class A { ... } in Java is equal to open class A { ... } in Kotlin.
final class B { ... } in Java is equal to class B { ...} in Kotlin.
It is not related with public.
In Kotlin, everything without access modifiers is public by default. You can explicitly say public in the definition, but it is not necessary in Kotlin.
So,
public class A { ... }
and
class A { ... }
are the same in Kotlin.
I put here just for my memo, maybe useful for someone else :
open class in kotlin means that a class can be inherited because by default they are not:
class Car{....}
class Supercar:Car{....} : // give an error
open Car2{....}
class Supercar:Car2{....} : // ok
public class in Java is about the visibility of class (nothing to do with inheritance : unless a class in java is final, it can be inherited by default).
In kotlin all the class are public by default.
open method in kotlin means that the method can be overridden, because by default they are not.
Instead in Java all the methods can be overridden by default
The method of an open class cannot be overridden by default as usual (doesn't matter if the class is open), they must be declared that they can be overridden :
open class Car{
fun steering{...}
}
class Supercar:Car{
override fun steering {...} // give an error
}
open class Car2{
open fun steering{...}
}
class Supercar:Car2{
override fun steering {...} // ok
}
for more details : https://kotlinlang.org/docs/reference/classes.html
public: public keyword in Kotlin is similar to java it is use to make the visibility of classes, methods, variables to access from anywhere.
open: In Kotlin all classes, functions, and variables are by defaults final, and by inheritance property, we cannot inherit the property of final classes, final functions, and data members. So we use the open keyword before the class or function or variable to make inheritable that.
open is opposite to Final in java.
If the class is not 'open', it can't be inherited.
class First{}
class Second:First(){} // Not allowed. Since 'First' is Final(as in Java) by default. Unless marked "open" it can't be inherited
Don't get confused with open and public. public is a visibility modifier
class Third{} // By default this is public
private class Fourth{}
class Fifth{
val third = Third() // No issues
val fourth = Fourth() // Can't access because Fourth is private
}
All classes, methods, and members are public by default BUT not open
Keyword open in kotlin means "Open for Extension"
means if you want any class to be inherited by any subclass or method to be overriden in subclasses you have to mark as open otherwise you will get compile time error
NOTE: abstract classes or methods are open by default you do not need to add explicitly.
OPEN VS FINAL VS PUBLIC
OPEN :
child class can access this because they are inherited by its parent.
In Kotlin you need to add 'open' keyword unlike java whose all classes are 'open' by default
Example :
Kotlin : open class A () {}
Java : class A () {}
FINAL :
child class can't access or inherit.
In JAVA you need to add 'final' keyword unlike kotlin whose all classes are 'final' by default
Example :
Kotlin : class A () {}
Java : final class A () {}
PUBLIC : Any class whether its inherited or not can access its data or methods.
Example in Kotlin :
//Final
class DemoA() {
protected fun Method() {
}
}
class DemoB() : DemoA {
Method() // can't access
}
//OPEN
open class DemoA() {
protected fun Method() {
}
}
class DemoB() : DemoA {
Method() // can access
}
//Public
class DemoA() {
fun Method() {
}
}
class DemoB() {
val a = DemoA()
a.Method() // can access
}
Example in Java :
//FINAL
final class DemoA() {
protected void name() {
}
}
class DemoB() extends DemoA {
name(); // Can't access
}
//Open
class DemoA() {
protected void name() {
}
}
class DemoB() extends DemoA {
name(); // Can access
}
//Public
class DemoA() {
void name() {
}
}
class DemoB(){
DemoA a = new DemoA()
a.name(); // Can access
}
Summarized answer (Kotlin)
The defaults of declarations of classes, methods, and properties are
(public + final). final prevents any inheritance attempts.
In order to be able to extend a class, you must mark the
parent class with the open keyword.
In order to be able to override the methods or properties, you must
mark them in the parent class with the open keyword, in addition to
marking the overriding method or parameter with the override keyword.
public is just encapsulation, it affects the visibility of classes/ methods. Public will make them visible everywhere.
Reference

how can I do if many class inherit one interface with Ninject.Extensions.Conventions

In my item,there are multi class inherit one interface, and many interface like this.
for example,class A|B|C inherit interface Ilog, class F|E|G inherit interface IData, and class H|I|J inherit IBase, and so on. now ,I want bind All Interface use Ninject.Extensions.Conventions,how can I do. if use conventions can't do it,please tell me the best way to do it. and I want somebody tell me how use Ninject.Extensions.Conventions in Item,don't tell me the concrete syntex,I want to know how to organize my class and Interface let bind interface easier,Thank you for your help!
code example like this:
public interface Ilog
{
//... ...
}
public class A:IIlog
{
//... ...
}
public class B:ILog
{
//... ...
}
public class C:ILog
{
//... ...
}
public interface IData
{
//... ...
}
public class H:IData
{
//... ...
}
public class E:IData
{
//... ...
}
public class G:IData
{
//... ...
}
public interface IBase
{
//... ...
}
public class H:IBase
{
//... ...
}
public class I:IBase
{
//... ...
}
public class J:IBase
{
//... ...
}
now,I want resolve interface Ilog to A,IData to E,IBase to H,how can I Do with Ninject.Extensions.Conventions? if many interface like this,how can I do?