Is it possible to realize (possibly with hacks) tr...
# javascript
t
Is it possible to realize (possibly with hacks) trait logic in last KotlinJS? In my case I have logic:
Copy code
interface A {
   fun doOne() // must be overrided
   fun doTwo() = definedExternally
}

class B: A {
   override fun doOne() { // do something  }

class C: A {
   override fun doOne() { // do something }
}
b
turansky: should
A
be
external
interface in your case?
or you want to have kotlin
interface A
with “optional” function?
^^^ @turansky
t
A
must be external
This is the main problem. In my case most of interfaces already realized. And I need to combine them in some classes if needed.
Mixins - first analogy. In JS it must be realized like mixins as I understand.
@aimozg, I create wrappers for library, which already has such logic and I want to realize wrappers in standard way.
a
@turansky sorry, I still don't get it. Are you trying to declare member that could be either overridden or injected in external JS?
k
What's the problem to declare
doOne
as a member method?
t
Problem - how to say,
doTwo()
already realized externally
No problems with
doOne
Updated example:
Copy code
external interface A {
   fun doOne() // must be overrided
   fun doTwo() = definedExternally
}

external open class B: A {
   override fun doOne() { // do something  }

external open class C: A {
   override fun doOne() { // do something }
}
Line
fun doTwo() = definedExternally
will not be compiled
But interface
A
already realize this method
a
are you going to subclass
interface A
or
class B
?
in Kotlin
t
Yes
It must be possible
a
which one? both of them?
t
Both
Class wrappers are opened for inheritance
b
Try something like that:
Copy code
@JsName("A")
external class AImpl

val protoA = AImpl::class.js.asDynamic().prototype

interface A {
    fun foo()
    fun bar(a: Int) = protoA.bar.call(this, a)
    // or
    fun baz(b: Int) = js("A.prototype.baz.call(this, b)")
    // or
    fun boo(b: Int) = js("A.prototype.baz.call(this, arguments)")
}
t
Zalim, second variant will work only with classes defined globally (not my case). What about first? Will it work if I will define
file:JsModule(”modules/A.js")
?
b
Yes, I think it should work, but the annotation will force you to extract your non-external declarations
t
What about cases, when
bar
realization use
foo
implementation?
It also will work?
b
other solutions:
Copy code
// mix from object
external interface A {
    fun bar(a: Int)
}

external val b: A 

class D : A by b

// mix from A.prototype
@JsName("A")
external class AIMpl
val p: A AIMpl::class.js.asDynamic().prototype

class E : A by p
It also will work?
I think yes. Just try 🙂
t
External type extends non-external type
Copy code
@JsName("A")
external class AImpl

val protoA = AImpl::class.js.asDynamic().prototype

interface A {
    fun foo()
    fun bar(a: Int) = protoA.bar.call(this, a)

external class B: A { // ERROR IS HERE
}
t
Zalim, I do not undersdand ‘magic’ of this solution
Copy code
// mix from object
external interface A {
    fun bar(a: Int)
}

external val b: A 

// mix from A.prototype
class D : A by b
This is first solution?
b
it’s last
which “magic" You don’t understand?
t
Copy code
// mix from object
external interface A {
    fun barA(a: Int)
}

external interface B {
    fun barB(a: Int)
}

external val AImpl: A
external val BImpl: B

// mix from A.prototype
external class D : A by AImpl, B by BImpl
In such case I have error -
Can’t use delegate on external class
b
You should not use it for external classes
we don’t change any external declaration
is it right that your library mixed
A
and
B
to
D
itself?
if so just say
external class D : A, B
and declare overrides
t
For generation it’s not a problem
I can generated such methods, but in work it will be broblem
For example I have interface
IList
It has 20 methods. Really I need to implement only 4 from them, other 16 are already implemented.
It simply kill idea to use KotlinJS, because of ‘stupid’ wrappers.
In most cases implemented methods are final.
b
If you provide real example I can try to help you
You can do it privately (by DM) if necessary
t
In
Table
realization must be overrided only abstract methods.
50% of
ITable
methods are already implemented
a
then why you need an
interface
and not just superclass?
t
And for example if I have
MyTable
realization I want to implement only methods marked like
abstract
then why you need an
interface
and not just superclass?
In this case I will not have ability to implement multiple interfaces
a
But the interface does not have superclass constructor call (right?)
(In the Kotlin)
t
Right
Possibly it will help to understand problem
@bashor, any ideas about problem solving?
@bashor, @konsoletyper, such problem also must be solved in ts2kt? Or it already solved?
@bashor, any ideas?
b
@turansky, sorry, I didn’t look to it yet, I’ll ping you later (probably tomorrow)
t
Ok
@bashor, any news about mixins realization? If it is unpossible now without big hacks, please write about that. Problem isn’t so big for now.
@bashor ?
b
@turansky oh, very sorry, I was busy with RC. I'll try to take a look on it on next week.
t
For now I have workaround, and some traits I declare like abstract classes and remain only one trait as implemented (if more than one declared) - such logic realized in GWT overlays. That is why standard realization of traits is more interesting. As I understand mixin logic will be realized in next versions of KotlinJS, otherwise how you will support TypeScript descriptors?
b
Hi, @turansky! AFAIK TypeScript don’t have builtin support for mixins, But you can write some code to emulate it. As I see in TypeScript
ITable
declared as interface so for TypeScript it’s some declaration which exist only at compile time.
In your example you probably should inherit from `Table`class instead of
ITable
Unfortunately, as I understand, the library is closed and I can’t how it works internally or/and play with examples
As I see here http://docs.yworks.com/yfileshtml/#/dguide/framework_basic_interfaces#framework_implementing_interfaces You can write something like:
Copy code
kotlin
// FILE: d.kt

@file:JsQualifier("yfiles.graph")
package yfiles.graph

external interface ITable {
	fun foo()
	fun bar() = 2
}

@JsName("ITable")
external class ITableImpl


// FILE: d2.kt

@file:JsQualifier("yfiles.lang")
package yfiles.lang

external class Class {
	val prototype: dynamic
}

// FILE: usage.kt

class MyTable : ITable by ITableImpl::class.js.asDynamic().prototype

class MyTable2 : ITable by yfiles.lang.Class(ITableImpl::class.js).prototype
Please try and let me know results
another way is play with
yfiles.lang.BaseClass
t
@bashor Thanks. I will try described logic this week. In your example I do not see you resolve traits problem. In this example only I will need declare only nonimplemented methods?
Copy code
class MyTable : ITable by ITableImpl::class.js.asDynamic().prototypeclass MyTable : ITable by ITableImpl::class.js.asDynamic().prototype
I will try in any case. In
geometry
package exists classes, which implements 2 or 3 traits. For example http://docs.yworks.com/yfileshtml/#/api/yfiles.geometry.OrientedRectangle. Such classes also can be realized, right?
b
In this example only I will need declare only nonimplemented methods?
Yes, I think it should work, but it will not force you to implement all members
In
geometry
package exists classes, which implements 2 or 3 traits.
Looks like inheritance from classes should work out of box