适用于JavaScript的Kotlin可配置工厂

时间:2017-02-09 09:12:53

标签: kotlin

我有一个Kolin类A,其属性在主构造函数中提供,或者由A的辅助构造函数中的工厂创建。

interface I

class O : I

class A (val i: I) {
    constructor(): this(factory!!.create())
}

interface Factory {
    fun create(): I
}

class MyFactory: Factory {
    override fun create(): I {
        return O()
    }
}

var factory: Factory? = null

fun main(args: Array<String>) {
    factory = MyFactory()
    A()
}

当我将此代码编译为JavaScript(Kolin Compiler版本1.0.6-release-127)并在浏览器(Safari 10.0.3)中运行时,我收到以下运行时错误:

ReferenceError:Can't find variable: tmp$0

错误发生在A的辅助构造函数中。看起来Kolin在辅助构造函数中执行参数的空检查时遇到问题。当我将工厂声明更改为“not null”并从main()方法中删除工厂初始化时,代码正确运行:

val factory: Factory = MyFactory()

fun main(args: Array<String>) {
    A()
}

但这不是我想要的,因为我希望能够在应用程序启动时配置工厂。

我是否想念一些东西,或者这是Kotlin的JavaScript编译器中的错误?有人知道这个问题的解决方法吗?是否有另一种或更好的方法可以在Kotlin中为JavaScript设计可配置的工厂?

生成的JavaScript代码:

var KotlinTest = function (Kotlin) {
  'use strict';
  var _ = Kotlin.defineRootPackage(function () {
    this.factory = null;
  }, /** @lends _ */ {
    I: Kotlin.createTrait(null),
    O: Kotlin.createClass(function () {
      return [_.I];
    }, function O() {
    }),
    A: Kotlin.createClass(null, function A(i) {
      this.i = i;
    }),
    A_init: function ($this) {
      $this = $this || Object.create(_.A.prototype);
      _.A.call($this, ((tmp$0 = _.factory) != null ? tmp$0 : Kotlin.throwNPE()).create());
      return $this;
    },
    Factory: Kotlin.createTrait(null),
    MyFactory: Kotlin.createClass(function () {
      return [_.Factory];
    }, function MyFactory() {
    }, /** @lends _.MyFactory.prototype */ {
      create: function () {
        return new _.O();
      }
    }),
    main_kand9s$: function (args) {
      _.factory = new _.MyFactory();
      _.A_init();
    }
  });
  Kotlin.defineModule('KotlinTest', _);
  _.main_kand9s$([]);
  return _;
}(kotlin);

1 个答案:

答案 0 :(得分:0)

回答我自己的问题。正如@marstran正确评论的那样,这似乎是Kolin的Javascript编译器1.0.6中的一个错误,它似乎在1.1-beta中得到修复。与此同时,我正在使用类似于以下内容的解决方法:

interface I

class O : I

class A (val i: I) {
    constructor(): this(Factory.get().create())
}

interface Factory {

    companion object {
        private var IMPL : Factory? = null
        fun get(): Factory = IMPL!!
        fun set(impl: Factory) {
            IMPL = impl
        }
    }

    fun create(): I
}

class MyFactory: Factory {
    override fun create(): I {
        return O()
    }
}

fun main(args: Array<String>) {
    Factory.set(MyFactory())
    A()
}