[問題] Scala 的 Covariant/Contravariant/Inv …

看板PLT (程式語言與理論)作者 (邀怪)時間15年前 (2009/03/15 01:20), 編輯推噓2(200)
留言2則, 2人參與, 最新討論串1/17 (看更多)
看到 godfat 大大在 Java 版提到 Scala 的 Variant 方式, 覺得很有趣, 上網找了 Scala 的資料看了一下, 發現 Scala 的 type variance 選擇還真多, 三種 variance 方法都允許, 而且是可以直接應用在 type parameter 上面. 但是仔細想想, 就開始懷疑某些 variance 在實務上的實用性, 甚至有時候會干擾原先 OO 的語意? 譬如從 Covariant 開始, 如果定義 List[+T], 則只要 A 是 subclass of B (這裡用 A < B 表示), 則 List[A] < List[B]. 從 OO 的觀點, 這表示 List[A] 可以被當成 List[B] 用在所有 List[B] 出現的地方. 但實際上卻不然, List[B].add(B) 就不該能用 List[A].add(B) 才對. Java 的 array 就是 covariant, 變得會允許下面這種不正當的操作: String[] s = new String[5]; Object[] o = s; // array is covariant so this is allowed o[3] = new Object(); String name = s[3]; // throws ArrayStoreException ! 反過來, Contravariant 就更令我納悶了, 如果定義 List[-T], 表示當 B < A, 則 List[A] < List[B]... that makes my head spin... 所以如果用 Java 的 pseudo code 來表示, 變成: Object[] o = new Object[5]; String[] s = o; // this is allowed if contravariant 真的會有好的理由在實務上需要這樣的 variant 嗎? 在我自己的感覺, 這種功能造成的問題可能比解決的問題還多... 最後 Invariant, 這就很直接了, 如果定義 List[T], 則不論 A < B 或 B < A, List[A] 跟 List[B] 互相完全沒關係, 這最保守, 最不會干擾 OO 的語意, 但是也最不靈活. Java 的 type parameter 就選擇了這種, 只是加上了一些 bounded type 定義 讓它稍微靈活一點, 但基本上還是 Invariant. 或許 template based polymorphism 本質上就跟 class based polymorphism 不一樣, 所以湊在一起就是會有衝突的地方吧? 感覺上 Java 比較保守, 盡量維持 class based typing 的一致性, 而 Scala 就蠻大膽的, 全部放進去看看大家怎麼用 (functional programming? anyone? ...) 哈, 突然想到一句話: "High explosives, handle with care." -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.165.166.80

03/15 01:48, , 1F
久違的心得好感動啊... 晚了明日再回 @@
03/15 01:48, 1F

03/17 09:44, , 2F
簡直感動到痛哭流涕呀 ~
03/17 09:44, 2F
文章代碼(AID): #19k-T47f (PLT)
討論串 (同標題文章)
文章代碼(AID): #19k-T47f (PLT)