インタフェースとvirtual,override,newキーワード

7839 ワード

一、クラス継承インタフェース
1まず、簡単なITeacherインタフェースを定義し、Professorクラスが継承することを定義します.
        public interface ITeacher
        {
            void Print();
        }

        public class Professor : ITeacher
        {
            public void Print()
            {
                Debug.Write("I'm Professor!");
            }
        }
            ITeacher teacher = new Professor();
            teacher.Print();
    :I'm Professor!

2,ProfessorクラスのPrintメソッドをVirtualに変更するとどうなりますか?
        public class Professor : ITeacher
        {
            public virtual void Print()
            {
                Debug.Write("I'm Professor!");
            }
        }

出力結果:I'm Professor!
Virtualの加入は,インタフェースの動作を変更していないが,このキーワードがあれば,サブクラスでProfessorクラスのPrintメソッドを書き換えることができる.
3、AssistantProfessorクラスを定義し、Professorクラスから継承します.
        public class AssistantProfessor : Professor
        {
            public override void Print()
            {
                Debug.Write("I'm AssistantProfessor!");
            }
        }

            ITeacher teacher = new AssistantProfessor();
            teacher.Print();

 
結果出力:I'm AssistantProfessor!
なお、ProfessorはITeacherインタフェースを継承しており、そのサブクラスAssistantProfessorはこのインタフェースを継承する必要がなくなり、サブクラスのデフォルトでもこのインタフェースが実現され、サブクラスAssistantProfessorクラスがPrintメソッドを実装しない場合、インタフェースは親クラスProfessorのPrintメソッドを呼び出す.サブクラスAssistantProfessorがoverride親クラスProfessorのPrintメソッドを書き換えると、インタフェースはサブクラスAssistantProfessorのPrintメソッドを呼び出します.これは実際にはクラスの継承呼び出しと一致しており、この原理をマルチステートで説明できます.
4,サブクラスAssistantProfessorでnewキーを使用した場合、結果はどうなりますか?
        public class AssistantProfessor : Professor
        {
            public new void Print()
            {
                Debug.Write("I'm AssistantProfessor!");
            }
        }

上のコードコンパイルに問題はありません.サブクラスAssistantProfessorのPrintメソッドには、親を隠すPrintメソッドを表すnewキーワードが追加されています.
親の書き換えではなく、マルチステートがなくなり、インタフェースが親のPrintメソッドを呼び出すので、結果出力:I'm Professor!
5,孫類のPrintメソッド、インタフェースはまだ呼び出すことができますか?
        public class Professor : ITeacher
        {
            public virtual void Print()
            {
                Debug.Write("I'm Professor!");
            }
        }

        public class AssistantProfessor : Professor
        {
            public override void Print()
            {
                Debug.Write("I'm AssistantProfessor!");
            }
        }

        public class SubAssistantProfessor : AssistantProfessor
        {
            public override void Print()
            {
                Debug.Write("I'm SubAssistantProfessor!");
            }
        }

            ITeacher teacher = new SubAssistantProfessor();
            teacher.Print();

 
上のコード、実行結果:I'm SubAssistantProfessor!
ここは依然として多態の役割で、皆さんが気づいていないことを知らないで、サブクラスAssistantProfessorはoverrideキーワードを使って、孫類SubAssistantProfessorは意外にもoverrideキーワードを使うことができて、virtualと宣言する方法だけがoverrideではありませんか?
逆コンパイルツールを使用すると、override付きの方法が明確に表示され、コンパイルされた後も虚の方法であり、書き換えることができます.と思うのですが、
これも多態の意味であり、後生類はそれぞれ異なる行為を示すことができる.
	// Methods
	.method public hidebysig virtual 
		instance void Print () cil managed 
	{
		// Method begins at RVA 0x22bb
		// Code size 13 (0xd)
		.maxstack 8

		IL_0000: nop
		IL_0001: ldstr "I'm AssistantProfessor!"
		IL_0006: call void [System]System.Diagnostics.Debug::Write(string)
		IL_000b: nop
		IL_000c: ret
	} // end of method AssistantProfessor::Print

6,サブクラス表示実装インタフェース
        public interface ITeacher
        {
            void Print();
        }

        public class Professor : ITeacher
        {
            public virtual void Print()
            {
                Debug.Write("I'm Professor!");
            }
        }

        public class AssistantProfessor : Professor, ITeacher
        {
            public new void Print()
            {
                Debug.Write("I'm AssistantProfessor!");
            }
        }

            ITeacher teacher = new AssistantProfessor();
            teacher.Print();

上の例と上の例4は少し違いますが、サブクラスAssistantProfessorはITeacherインタフェースが実装されていることを示しています.このときITeacher変数で直接見つけたのがサブクラスAssistantProfessorのPrintメソッドなので、出力結果は:I'm AssistantProfessor!
このコードを見てみましょう.
        public interface ITeacher
        {
            void Print();
        }

        public class Professor : ITeacher
        {
            public virtual void Print()
            {
                Debug.Write("I'm Professor!");
            }
        }

        public class AssistantProfessor : Professor, ITeacher
        {
        }

上のコードの結果:I'm Professor!
サブクラスはIteacherインタフェースを定義しているが、実装は提供されていない.
このコードを見てみましょう.
        public interface ITeacher
        {
            void Print();
        }

        public class Professor 
        {
            public virtual void Print()
            {
                Debug.Write("I'm Professor!");
            }
        }

        public class AssistantProfessor : Professor, ITeacher
        {
        }

このコードはコンパイルできますか?親はITeacherインタフェースを実装せず,子はIteacherインタフェースを実装したが,実装方法は提供されなかった.
不思議なことに、コンパイルできて、実行結果は:I'm Professor!間違いない!親クラスはITeacherで定義されたメソッドを実装し,子クラスは実装しなくてもよい.
上の例は予想外かもしれませんが、インタフェースの呼び出し順序を大まかにまとめて、奇妙な問題を説明することもできます.
7,以上の実験から,簡単にまとめ,インタフェースメソッド実行時の検索順序:
1)インスタンスクラスが直接インタフェースを継承している場合、インスタンスクラスにインタフェースメソッドがあるかどうかを検索し、ある場合は直接実行する.ない場合は、インスタンスクラスの親クラスにインタフェースメソッドがあるかどうかを検索し、ある場合は実行します.(見つからないことはあり得ません.そうしないとコンパイルは通じません)
2)インスタンスクラスがインタフェースを直接継承していない場合は、まず実装インタフェースの親を検索し、次に親クラスにインタフェースメソッドがあるかどうかを検索し、ある場合はメソッドがvirtualメソッドであるかどうかを確認し、ある場合はインスタンスクラスが書き換えられているかどうかを確認し、書き換えられている場合はインスタンスクラスのメソッドを呼び出し、書き換えていない場合は親クラスのvirtualメソッドを直接呼び出す.インタフェースを実装する親にインタフェースメソッドが見つからない場合は、親の親が見つかるまで検索し、そのメソッドを実行します.(同じように、見つからないこともあり得ません.そうしないとコンパイルが通じません)
二、インタフェース間の継承
1,インタフェースはインタフェースを継承することができる
        public interface ITeacher
        {
            void Print();
        }

        public interface IGoodTeacher : ITeacher
        {
            void Read();
        }

IGoodTeacherを継承するクラスを定義する場合は、PrintメソッドとReadメソッドを同時に実装する必要があります.そうしないとコンパイルエラーが発生します.
        public class Professor : IGoodTeacher
        {
            public void Print()
            {
                Debug.Write("I'm Professor! Print");
            }

            public void Read()
            {
                Debug.Write("I'm Professor! Read");
            }
        }

2,サブクラスProfessorを継承すると、IGoodTeacherも自動的に継承されます
        public class AssistantProfessor : Professor
        {
        }

AssistantProfessorはメソッドを提供していません.AssistantProfessorがIGoodTeacherインタフェースの継承を表示していても、親がこれらのメソッドを提供しているため、メソッドは提供されません.これは、前述したクラス継承インタフェースの分析方法と一致しています.ここでは、さらなる議論はしません.