初始化接口实例变量

时间:2018-02-18 23:00:56

标签: interface kotlin

我想通过使用接口在Kotlin类中注入(丰富)行为和状态。与class Impl : Observable类似,Observable包含状态。

在Scala中使用Traits(确实有效),为此寻找Kotlin解决方案:

object Test extends App {
  val impl = new Impl()
  val observer = new Observer()
  impl.register(observer)
}

trait Observable {
  // How to do this in Kotlin?
  val observers = List()

  def register(observer: Observer) {
    observers.add(observer)
  }
}
class Observer

class Parent
class Impl extends Parent with Observable

在Kotlin尝试(不工作):

fun main(args: Array<String>) {
    val impl = Impl()
    val observer = Observer()
    impl.register(observer)
}

interface Observable {
    // Error: Kotlin: Property initializers are not allowed in interfaces
    val observers = mutableListOf<Observer>()

    fun register(observer: Observer) {
        observers.add(observer)
    }
}
class Observer

open class Parent
class Impl : Parent(), Observable

在接口实例变量行导致此错误:Kotlin: Property initializers are not allowed in interfaces。 如何在Kotlin接口中初始化实例变量? (请注意,在此设计中,不应更改/更新父类。)

更新:我在Java中有一个示例解决方案,但行为不正确。 Java接口中的“实例变量”是自动静态的。所以我删除了那个例子。

2 个答案:

答案 0 :(得分:3)

您可以在Kotlin接口中拥有一个for的占位符,并让实现类提供该状态。因此,接口可以提供与预期存在状态相反的功能。如:

class Observer

interface Observable {
    val observers: MutableList<Observer> // not present, but expected

    fun register(observer: Observer) {
        observers.add(observer)
    }
}

open class Parent

class Impl : Parent(), Observable {
    override val observers = mutableListOf<Observer>() // used by the interface
}

这是有充分理由的,存在一些微妙的问题,即状态来自类层次结构中的多个项目,而Kotlin正在防止这些模型可能出现的问题。

答案 1 :(得分:2)

在Java中,你实际上有一个静态字段,而不是一个实例字段(与Scala代码不同,它可以按预期工作):

  

Every field declaration in the body of an interface is implicitly public, static, and final.

通过将字段放入伴随对象,您可以在Kotlin中实现相同的行为。

但你应该做的是使用public static void ValidateCheck(DataGridView dataGridView, CheckBox[] chk) { FileStream fs = new FileStream(@"C:\brandon\InvalidColumnCheck.txt", FileMode.OpenOrCreate, FileAccess.Write); StreamWriter sw = new StreamWriter(fs); sw.BaseStream.Seek(0, SeekOrigin.End); StringBuilder sb = new StringBuilder(); decimal num; sw.WriteLine("----------------------------"); sw.WriteLine(""); for (int j = 0; j < dataGridView.ColumnCount - 1; j++) { if (chk[j].Checked == true && chk[j].Name.Contains(dataGridView.Columns[j].Name)) { string column = chk[j].Name; for (int k = 0; k < dataGridView.RowCount; k++) { if (!Decimal.TryParse(dataGridView.Rows[k].Cells[column].Value.ToString(), out num)) { if (dataGridView.Rows[k].Cells[dataGridView.Columns[column].Name].Value.ToString() == null || dataGridView.Rows[k].Cells[dataGridView.Columns[column].Name].Value.ToString() == "" || dataGridView.Rows[k].Cells[dataGridView.Columns[column].Name].Value.ToString() == column) { } else { //MessageBox.Show("COLUMN" + dataGridView.Columns[j].Name.ToString() + "" + dataGridView.Rows[k].Cells[column].Value.ToString() + " NOT A DECIMAL!"); sb.AppendLine("[Column " + chk[j].Name.ToString().ToUpper() + "] :" + dataGridView.Rows[k].Cells[column].Value.ToString() + " NOT A DECIMAL!"); } } } sb.AppendLine(""); } } if (sb.ToString() == null || sb.ToString() == "" || sb.Length < dataGridView.Columns.Count) { sw.WriteLine("No Errors!"); sw.WriteLine(""); sw.WriteLine("----------------------------"); MessageBox.Show("No errors!"); Process.Start(@"C:\brandon\InvalidColumnCheck.txt"); } else if (sb.ToString() != null || sb.ToString() != "") { sw.WriteLine(sb.ToString()); sw.WriteLine("----------------------------"); //MessageBox.Show(sb.ToString()); Process.Start(@"C:\brandon\InvalidColumnCheck.txt"); } sw.Flush(); sw.Close(); } 而不是接口。

delegation

abstract class