2017-04-13 32 views
0

如果問題的標題不是真的很重要,我很抱歉,但我還沒有找到更好的方式來描述此問題。瞭解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的物化和泛型是如何工作的?

回答

2

這是所有關於原始類型,kotlin不允許。

這種格式的工作原理:

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

這兩者並不:

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

所以現在事情得到清晰的。 TextOutputFormat是非法的,因爲Kotlin不允許使用原始類型。您必須指定(2)中缺少的類型參數。添加它們將導致格式(1)。

這看起來有點冗長,但目前沒有解決方法(至少恕我直言)。

+0

感謝您的澄清,但我應如何更改'Job.addMultipleNamedOutput'的簽名以使可能(1)?因爲現在它只接受(2),而對於(1)它抱怨丟失的鍵和值。 – gmariotti

+0

對不起,我犯了一個錯誤。我非常抱歉。 – glee8e