我想通过使用接口在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接口中的“实例变量”是自动静态的。所以我删除了那个例子。
答案 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
, andfinal
.
通过将字段放入伴随对象,您可以在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();
}
而不是接口。
abstract class