ufcpp / UfcppSample

http://ufcpp.net/ 向けのサンプル
Apache License 2.0
136 stars 39 forks source link

インターフェイスのデフォルト実装 #251

Closed ufcpp closed 5 years ago

ufcpp commented 5 years ago

参考: https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md https://ufcpp.net/blog/2018/12/cs8notyet/

C# チームは default interface methods (DIM)って呼んでたりする(たぶん、Java 由来)。 でも、メソッド以外にもいろんな関数メンバーを持てる C# 的には不正確。 .NET ランタイム側は DefaultImplementationsOfInterfaces という名前を採用。

https://ufcpp.net/study/csharp/oo_interface.html に改ページありで末尾に追記かな。

1ページ目の「インターフェイスは規約のみを定める」的な説明には変更不要。 実際、「インターフェイスって機能名のまま実装を持たせるの?」みたいなのは Java でも C# でも議論になったはず。 追加で、「基本的には規約のみを定めたいんだけど以下のようなメリットがあって C# 8.0/.NET Core 3.0 から…」みたいな文章入れとく。

「規約のみを定める」のクリーンさ以上のメリットとして、「後からの API 追加が破壊的変更にならない」が大きかった。

限定的ではあるもののトレイト的に使えるメリットも少しあり。 ただ、これは C# の場合、拡張メソッドでできることも多いのでメリット小。

Java, Swift にデフォルト実装機能があるので、その辺りとの interop (要するに Android/iOS interop)で必要になってるというのもある。

デメリットはひし形継承時に「どっちのメソッドを呼べばいいかわからなくなる」くらいだけど、コンパイル時にも実行時にもチェックあり。 大体はコンパイル時にはじけるはず。実行時に問題を起こすのは「あとからのDLL差し替え」みたいなのしたときだけ。System.Runtime.AmbiguousImplementationException が発生。 コンパイル時の問題回避策は↓これ。

関連: https://github.com/ufcpp/UfcppSample/issues/244

関数メンバーの実装は認めるものの、フィールドはいまだ認めず。 (なので、「トレイトとしては限定的」になる。) フィールドのひし形継承はちょっとメリット以上の問題起こす。フィールドが2重になったり、メモリレイアウトをvirtualに解決しないといけなくなってパフォーマンスのデメリットがきつかったり。

細かく言うと以下の3つの機能に分かれる

abstract クラスとの差は縮まったものの、「フィールドの有無」が決定的な差。 細かいところだと、コンストラクター、デストラクター、演算子とかが不可。

あと、「修飾子未指定の場合の挙動」が全然違う。 クラスはあくまで private で non-virtual。 インターフェイスは public virtual。private か sealed を指定した時だけ non-virtual。

派生インターフェイスでデフォルト実装を override したい場合は常に明示的実装が必要。 base.M() 呼び出しも、インターフェイスのやつはできない。base(T).M() が必須。

デフォルト実装持ちで、自身が override してないメソッドを M() だけ呼ぶこともできない。((T)this).M() か、↑の base 呼びに。 (これは既存コードの互換性のためっぽい?) そういう意味でもトレイトとしては微妙。

「古いランタイム上では使えない機能」、「そういう機能追加は .NET Framework 2.0 以来14年ぶりの出来事」みたいな話は RuntimeFeature の専用別ページを study/csharp 以下に正式に設けてそっちに書きたい。 もしかしたら ブログの方 にリンクだけでいいかも。

ufcpp commented 5 years ago

https://ufcpp.net/study/csharp/cheatsheet/ap_ver8/ https://ufcpp.net/study/csharp/oo_interface.html?p=5#dim

RuntimeFeature はいったんブログの方にリンク。

ufcpp commented 5 years ago

https://twitter.com/ufcpp/status/1125010561870073857

変更かかりそうなので reopen。

ufcpp commented 5 years ago

16.2 Preview 1 で base(T) なくなってるの確認。

ufcpp commented 5 years ago

base(T) の話修正。

結局、「8.0 に入る予定で一時的には実装され値えたけど、カットされて 9.0 で再検討の予定」的な話を追記。