100165817.htm
来自「C#高级编程(第三版),顶死你们。。 。up」· HTM 代码 · 共 292 行 · 第 1/5 页
HTM
292 行
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 60.3pt"><span lang="EN-US">//etc.</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">如果在类定义中没有指定基类,</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">编译器就假定</span><span lang="EN-US">System.Object</span><span style="FONT-FAMILY: 宋体">是基类。因此下面的两段代码生成相同的结果:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">class MyClass : </span><span lang="EN-US">Object //derives from System.Object</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> //etc. </span></p>
<p class="2" style="MARGIN: 0cm 0cm 6.5pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">和</span></p>
<p class="2" style="MARGIN: 6.5pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">class MyClass</span><span lang="EN-US"> //derives from System.Object</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> //etc. </span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">为了简单一些,第二种形式比较常用。</span></p>
<p class="MsoNormal"><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">支持</span><span lang="EN-US">object</span><span style="FONT-FAMILY: 宋体">关键字,它用作</span><span lang="EN-US">System.Object</span><span style="FONT-FAMILY: 宋体">类的假名,所以也可以编写下面的代码:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">class MyClass : o</span><span lang="EN-US">bject //derives from System.Object</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> //etc. </span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">如果要引用</span><span lang="EN-US">Object</span><span style="FONT-FAMILY: 宋体">类,可以使用</span><span lang="EN-US">object</span><span style="FONT-FAMILY: 宋体">关键字,智能编辑器</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">如</span><span lang="EN-US">VS.NET)</span><span style="FONT-FAMILY: 宋体">会识别它,并对代码进行合适的编辑。</span></p>
<h3 style="MARGIN: 8.15pt 0cm"><span lang="EN-US">4.2.1</span><span lang="EN-US"> </span><span style="FONT-FAMILY: 黑体">虚方法</span></h3>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">把一个基类函数声明为</span><span lang="EN-US">virtual</span><span style="FONT-FAMILY: 宋体">,该函数就可以在任何派生类中重写了:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span><span lang="EN-US">class MyBaseClass</span></span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> public virtual</span><span lang="EN-US"> string VirtualMethod()</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> return "This method is virtual and defined in MyBaseClass";</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">也可以把属性声明为</span><span lang="EN-US">virtual</span><span style="FONT-FAMILY: 宋体">。对于虚属性或重写属性,语法与非虚属性是相同的,但要在定义中加上关键字</span><span lang="EN-US">virtual</span><span style="FONT-FAMILY: 宋体">,其语法如下所示:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">public virtual string ForeName</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> get { return foreName; }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> set { foreName = value; }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> </span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">private string foreName;</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">为了简单起见,下面的讨论将主要集中于方法,但其规则也适用于属性。</span></p>
<p class="MsoNormal"><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">中虚函数的概念与标准</span><span lang="EN-US">OOP</span><span style="FONT-FAMILY: 宋体">概念相同:可以在派生类中重写虚函数。在调用方法时,会调用对象类型的合适方法。在</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">中,函数在默认情况下不是虚拟的,但</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">除了构造函数以外</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">可以显式地声明为虚拟。这遵循</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">的方式,即从性能的角度来看,除非显式指定,否则函数就不是虚拟的,而在</span><span lang="EN-US">Java</span><span style="FONT-FAMILY: 宋体">中,所有的函数都是虚拟的。但</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">的语法与</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">的语法不同,因为</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">要求在派生类的函数重写另一个函数时,要使用</span><span lang="EN-US">override</span><span style="FONT-FAMILY: 宋体">关键字显式声明:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span><span lang="EN-US">class MyDerivedClass : MyBaseClass</span></span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> public override</span><span lang="EN-US"> string VirtualMethod()</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> return "This method is an override defined in MyDerivedClass";</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">方法重写的语法避免了</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">中很容易发生的潜在运行错误:当派生类的方法签名无意中与基类版本略有差别时,派生类方法就不能重写基类方法了。在</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">中,这会出现一个编译错误,因为编译器会认为函数已标记为</span><span lang="EN-US">override</span><span style="FONT-FAMILY: 宋体">,但没有重写它的基类方法。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">成员字段和静态函数都不能被声明为</span><span lang="EN-US" style="LETTER-SPACING: 0.1pt">virtual</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">,因为这个概念只对类中的实例函数成员有意</span><span style="FONT-FAMILY: 宋体">义。</span></p>
<h3 style="MARGIN: 8.15pt 0cm"><span lang="EN-US">4.2.2</span><span lang="EN-US"> </span><span style="FONT-FAMILY: 黑体">隐藏方法</span></h3>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">如果签名相同的方法在基类和派生类中都进行了声明,但该方法没有声明为</span><span lang="EN-US">virtual </span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"> override</span><span style="FONT-FAMILY: 宋体">,派生类方法就会隐藏基类方法。结果是调用哪个类的方法取决于用于引用实例的变量类型,而不是实例本身的类型。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在大多数情况下,是要重写方法,而不是隐藏方法,因为隐藏方法会存在为给定类的实例调用错误方法的危险。但是,</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">语法可以确保开发人员在编译时收到这个潜在错误的警告,使隐藏方法更加安全。这也是类库开发人员得到的版本方面的好处。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">假定有人编写了类</span><span lang="EN-US">HisBaseClass</span><span style="FONT-FAMILY: 宋体">:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">class HisBaseClass</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> // various members</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在将来的某一刻,要编写一个自己的派生类,给</span><span lang="EN-US">HisBaseClass</span><span style="FONT-FAMILY: 宋体">添加某个功能,特别是要添加一个目前基类中没有的方法</span><span lang="EN-US">MyGroovyMethod()</span><span style="FONT-FAMILY: 宋体">:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">class MyDerivedClass: HisBaseClass</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> public int MyGroovyMethod()</span></p>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?