C#の拡張メソッドとScalaの暗黙の型変換について

ufcppさんの考える理想系についてkmizuさんがヒアリング、みたいな構造
16

C#の「拡張メソッド」についてはここを参照。
MSDN 拡張メソッド (C# プログラミング ガイド)

Scalaの「暗黙の型変換」についてはここを参照。
Scala by Example 第 15 章 暗黙の引数と変換

話題の発端となったのはここ。
@IT 連載:[完全版]究極のC#プログラミング Chapter14 拡張メソッド


mutaguchi @mutaguchi

拡張メソッドはLINQのために追加された機能というのは分かるが、普通にIEnumerableのメソッドじゃダメだったのかと思ったりしていた:Chapter14 拡張メソッド - @IT http://t.co/hZwK82eU

2012-01-09 02:12:07
mutaguchi @mutaguchi

この記事によると既存ソースの互換性を保つためとか、LINQはオプションだから常に使うものではなく、オンオフできるのが望ましいから、という理由で拡張メソッドによる実装になったと考察されている。

2012-01-09 02:13:24
++C++; // 管理人: 岩永 @ufcpp

@mutaguchi インターフェイスに対して、後から第3者もたせるようにって考えると、静的メソッド以外ありえないんです。で、それを後起き記法しないといけない。

2012-01-09 02:14:28
++C++; // 管理人: 岩永 @ufcpp

@mutaguchi 2010年にもなって、拡張メソッドは使わない方が良いとかのうのうと言える記事は信じちゃダメです。

2012-01-09 02:15:37
mutaguchi @mutaguchi

@ufcpp 第三者にも拡張できるようにするためにそうしたんですね。第三者による拡張を考えなければ拡張メソッドなしでLINQを実装する道もあったのかなと思ったりしてました。

2012-01-09 02:20:58
++C++; // 管理人: 岩永 @ufcpp

@mutaguchi あんまり筋はよくないですけどねぇ。最初は確かに気持ち悪かったんですけど、考えれば考えるほど、今の実装しかなさげ。ScalaのTraitも、暗黙的型変換でのメンバー追加も、動的言語的なオープンクラスも、どれもデメリットでかすぎて。

2012-01-09 02:23:14
mutaguchi @mutaguchi

@ufcpp あ、この記事を信じるというわけじゃなくてむしろ変だなーと思って書き始めたのですが途中で中断しちゃいました^^;いや、LINQは常に使うものじゃないってことは今では考えられないですし。今やC#においてLINQは必須ですしねえ。

2012-01-09 02:24:58
neuecc @neuecc

@ufcpp @mutaguchi 次のJavaはinterfaceにデフォルト実装を設けることで、interfaceでメソッドライクに後置で書けるようにする、という方向で行くみたいですねー。というわけで後付けは出来ないけどLINQの実装は可能、と。

2012-01-09 02:28:43
++C++; // 管理人: 岩永 @ufcpp

@neuecc 結局、ScalaのTraitっぽいですよねぇ<デフォルト。あれは筋悪い。アルゴリズムを後から足せないとか、標準だけで何でもやる気なのかと。

2012-01-09 02:31:53
neuecc @neuecc

@ufcpp ですねえ。拡張メソッドっぽくやる、というアイディアが通ってたように見えた時期もあったので、なんでそっちに行ったのか……。

2012-01-09 02:34:06
mutaguchi @mutaguchi

@neuecc 後付けを考えないならそっち方向が素直ではありますよね。

2012-01-09 02:45:46

Java8では「仮想拡張メソッド(virtual extension method)」という名前で、interfaceメソッドにデフォルト実装を持たせられるという話。
詳しくはこちらを。Java 8 virtual extension methods

mutaguchi @mutaguchi

Javaの将来のバージョンでinterfaceに追加されるdefaultメソッド。インターフェースに実装を書けるようになるのね / “InfoQ: ラムダの現状” http://t.co/8ThbpGNm

2012-01-09 02:52:31
mutaguchi @mutaguchi

このデフォルトメソッドってのはそのインターフェースを実装したクラスで必ず実装しないといけないメソッドじゃなくて、クラスで実装がない場合に呼ばれるメソッド。

2012-01-09 03:13:35
mutaguchi @mutaguchi

ただC#の拡張メソッドみたいに、第三者が後付でメソッドを追加することはできない、と。

2012-01-09 03:28:07
mutaguchi @mutaguchi

インターフェースに単純にメソッドを追加してしまうと、そのインターフェースを実装したクラス全部に変更が必要になるけど、デフォルトメソッドの場合は既存のクラスもそのまま動くというわけか。

2012-01-09 03:14:47
mutaguchi @mutaguchi

拡張メソッドにせよデフォルトメソッドにせよ、互換性維持のための苦肉の策って感じがする。といってもコレクションとか配列みたいな基本的なクラスに互換性をなくすのも考えられない選択肢だったんだろうな。

2012-01-09 03:40:59

閑話休題。ここでkmizuさんが登場。


kmizu @kmizu

@ufcpp @mutaguchi 拡張メソッドを #scala のimplicit conversionによるメンバ追加や動的型付け言語によく見られるオープンクラスと比較するのはわかるんですが、traitsは(後付けでメンバ追加という点で)あんまり関係ないように見えます。

2012-01-09 02:53:08
kmizu @kmizu

@ufcpp @mutaguchi ちなみに、 #scala の暗黙的型変換によるメンバー追加の(拡張メソッドと比較した場合の)一番大きなデメリットってどの辺にあると思われますか?

2012-01-09 02:55:41
++C++; // 管理人: 岩永 @ufcpp

@kmizu traitsは関係ない方がいいんですけど、実際Scalaはtraitsでいろいろデータ処理メンバー持ってしまってるわけで。Javaもそれの後追いするようで…

2012-01-09 02:58:24
++C++; // 管理人: 岩永 @ufcpp

@kmizu それでのメンバー追加がダメなわけじゃなくて、暗黙の型変換自体がダメですよ。どこで何の型になってるかわかったもんじゃなく。

2012-01-09 02:59:54
kmizu @kmizu

@ufcpp うーむ。Scalaのtraitsがフィールド(というか状態)をメンバとして持てることを仰っているのでしょうか?Javaもそれの後追いするかというと、あれは確かメソッドのデフォルト実装をinterfaceにおけるだけで、全然違うような…。

2012-01-09 03:00:58
kmizu @kmizu

@ufcpp うーん。Scalaの暗黙の型変換の適用可能性は静的スコープによって制御されるわけで、無制約に適用されるわけじゃないんですけど、それでもダメですかね…。「どこで何の型になってるか」は少なくとも明確なような。

2012-01-09 03:04:07
1 ・・ 4 次へ