同一シグネチャのメソッドを持った別々のインタフェースを実装するとどうなるか
プログラミングC# 第四版 p166
タイトルからして分かりづらいですが、要はJavaでいうところのこういうことです。
- 同じシグネチャ(public void func())を持った
- 別々のインタフェース(IFunc1とIFunc2)を
- 実装したクラス(FuncImpl)はどうなるか。
ということですが、結果どうにもなりませんでした。
public class test { public static void main(String[] args) throws Exception { new test(); } public test() { FuncImpl f = new FuncImpl(); f.func(); IFunc1 if1 = f; if1.func(); IFunc2 if2 = f; if2.func(); System.out.println(IFunc1.f); System.out.println(IFunc2.f); // Error //System.out.println(FuncImpl.f); } interface IFunc1 { public static final int f = 10; public void func(); } interface IFunc2 { public static final int f = 20; public void func(); } class FuncImpl implements IFunc1, IFunc2 { public void func() { System.out.println("FuncImpl#func"); } } }
結果はこう。
>java test FuncImpl#func FuncImpl#func FuncImpl#func 10 20 >
メソッドについては、どっちのインタフェースを採用しても同じのため、結局どっちでもいいということらしい。
9.4.1 継承及び上書き
同じメソッド宣言が一つのインタフェースから継承される経路は,複数存在することがある。この事実は,いかなる困難も引き起こさず,決してそのままではコンパイル時エラーを生じない。
http://www.y-adagio.com/public/standards/tr_javalang/9.doc.htm#40247
この辺の記述がそうなのか?あいまいだけど。
ちなみに、定数フィールドについては、各インタフェースで別々の値を持つことができるので、どっちでもいいということはないです。
9.3.2.1 あいまいな継承フィールド
例えば直接的スーパインタフェース内の二つが同じ名前をもつフィールドを宣言しているために同じ名前をもつ二つのフィールドが一つのインタフェースによって継承されれば,一つのあいまいなメンバ(ambiguous members)のいかなる使用も,コンパイル時エラーを生ずる。
http://www.y-adagio.com/public/standards/tr_javalang/9.doc.htm#40247
ちなみにC#では、Javaのようにすることも出来ますが、それぞれのインタフェースごとに実装することも可能です。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { FuncImpl f = new FuncImpl(); //f.func(); IFunc1 if1 = f; if1.func(); IFunc2 if2 = f; if2.func(); } } interface IFunc1 { void func(); } interface IFunc2 { // Javaと違って、インタフェースに定数は入れられません。。 // private const int f = 10; void func(); } class FuncImpl : IFunc1, IFunc2 { //public void func() //{ // Console.WriteLine("FuncImpl#func called."); //} void IFunc1.func() { Console.WriteLine("FuncImpl#IFunc1.func called."); } void IFunc2.func() { Console.WriteLine("FuncImpl#IFunc2.func called."); } } }
結果はこう。
FuncImpl#IFunc1.func called. FuncImpl#IFunc2.func called.
名前空間ってことを考えると、こっちの方が言語仕様として正しいような気もします。