了解具体化和通配符在Kotlin中的工作原理

时间:2017-04-13 07:18:34

标签: generics kotlin

如果问题的标题不是很重要,我很抱歉,但我还没有找到更好的方法来描述这个问题。

我正在为Hadoop编写一些Kotlin扩展方法,昨天我发现了一个我不理解的奇怪错误。我写了几个这样的扩展方法:

inline fun <reified T : InputFormat<*, *>, reified K : Mapper<*, *, *, *>> Job.addMultipleInputPath(path: Path) {
  MultipleInputs.addInputPath(this, path, T::class.java, K::class.java)
}

inline fun <reified T : OutputFormat<*, *>, reified Key : Any, reified Value : Any> Job.addMultipleNamedOutput(namedOutput: String) {
  MultipleOutputs.addNamedOutput(this, namedOutput, T::class.java, Key::class.java, Value::class.java)
}

inline fun <reified T : Mapper<*, *, KeyClass, ValueClass>, reified KeyClass : Any, reified ValueClass : Any> Job.setMapper() {
  this.setMapperClass<T>()
  this.mapOutput<KeyClass, ValueClass>()
}

如果我尝试在我的Driver类中调用它们,(1)和(3)工作但是(2)给了我一个编译错误:

with(Job.getInstance()) {
  // works
  addMultipleInputPath<TextInputFormat, SensorsMapperType2>(secInput)

  // 2 type arguments expected for class TextOutputFormat<K: Any!, V: Any!> : FileOutputFormat<K!, V!> 
  // defined in org.apache.hadoop.mapreduce.lib.output
  addMultipleNamedOutput<TextOutputFormat, Text, SensorData>(HIGH_TEMP)

  // works
  setMapper<NGramMapper, Text, IntWritable>()
}

如果我使用<TextOutputFormat<Any, Any>>更正了通话,一切正常,但我不明白为什么会这样。对于Kotlin中的具体化和仿制学如何工作,我有什么遗漏吗?

1 个答案:

答案 0 :(得分:2)

关于原始类型,kotlin不允许这样做。

此格式有效:

addMultipleNamedOutput<TextOutputFormat, Text, SensorData>(HIGH_TEMP) //(2)

这两个人没有:

TextOutputFormat

现在事情变得清晰了。 @TypeDef(name = "hstore", typeClass = HstoreUserType.class) @Type(type="hstore") @Column(columnDefinition = "hstore") private HashMap<String,String> extraInfo; 是非法的,因为Kotlin不允许原始类型。您必须指定类型参数,这在(2)中缺失。添加它们会产生格式(1)。

这看起来有点冗长,但目前没有解决方法(至少恕我直言)。