100165819.htm
来自「C#高级编程(第三版),顶死你们。。 。up」· HTM 代码 · 共 264 行 · 第 1/4 页
HTM
264 行
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">namespace Wrox.ProCSharp.JupiterBank</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 class GoldAccount : IBankAccount</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-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">GoldAccount</span><span style="FONT-FAMILY: 宋体">类的细节,因为在本例中它基本上与</span><span lang="EN-US">SaverAccount</span><span style="FONT-FAMILY: 宋体">的实现相同。</span><span lang="EN-US">GoldAccount</span><span style="FONT-FAMILY: 宋体">与</span><span lang="EN-US">VenusAccount</span><span style="FONT-FAMILY: 宋体">没有关系,它们只是碰巧实现相同的接口而已。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">有了自己的类后,就可以测试它们了。首先需要一些</span><span lang="EN-US">using</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">using System;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">using Wrox.ProCSharp;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">using Wrox.ProCSharp.VenusBank;</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">using Wrox.ProCSharp.JupiterBank;</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">然后需要一个</span><span lang="EN-US">Main()</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">namespace Wrox.ProCSharp</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"> class MainEntryPoint</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"> static void Main()</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"> IBankAccount venusAccount = new SaverAccount();</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> IBankAccount jupiterAccount = new GoldAccount();</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> venusAccount.PayIn(200);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> venusAccount.Withdraw(100);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> Console.WriteLine(venusAccount.ToString());</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> jupiterAccount.PayIn(500);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> jupiterAccount.Withdraw(600);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> jupiterAccount.Withdraw(100);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> Console.WriteLine(jupiterAccount.ToString());</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">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">这段代码</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">如果下载本例子,它在</span><span lang="EN-US">BankAccounts.cs</span><span style="FONT-FAMILY: 宋体">文件中</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">的执行结果如下:</span></p>
<p class="a6" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">C:>BankAccounts</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">Venus Bank Saver: Balance = £100.00</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">Withdrawal attempt failed.</span></p>
<p class="a6" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">Jupiter Bank Saver: Balance = £400.00</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在这段代码中要注意的一个要点是把引用变量声明为</span><span lang="EN-US">IBankAccount</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: 宋体; LETTER-SPACING: -1pt">——</span><span style="LETTER-SPACING: -1pt"> </span><span style="FONT-FAMILY: 宋体">如果要调用由不是接口一部分的类执行的任何方法,就需要显式地把引用强制转换为合适的类型。在这段代码中,我们调用了</span><span lang="EN-US">ToString()(</span><span style="FONT-FAMILY: 宋体">不由</span><span lang="EN-US">IBankAccount</span><span style="FONT-FAMILY: 宋体">实现</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">,但没有进行任何显式转换,这只是因为</span><span lang="EN-US">ToString()</span><span style="FONT-FAMILY: 宋体">是一个</span><span lang="EN-US">System.Object</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">System.Object</span><span style="FONT-FAMILY: 宋体">的数据类型转换是隐式的</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。第</span><span lang="EN-US">5</span><span style="FONT-FAMILY: 宋体">章将介绍强制转换的语法。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">接口引用完全可以看做是类引用<span style="LETTER-SPACING: -1pt">——</span></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">IBankAccount[] accounts = new IBankAccount[2];</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">accounts[0] = new SaverAccount();</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">accounts[1] = new GoldAccount();</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">Note,however,that we'd get a compiler error if we tried something like this </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">accounts[1] = new SomeOtherClass(); // SomeOtherClass does NOT implement</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> // IBankAccount: WRONG!!</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">这会导致一个如下所示的编译错误:</span></p>
<p class="a6" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">Cannot implicitly convert type 'Wrox.ProCSharp.SomeOtherClass' to</span></p>
<p class="a6" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> 'Wrox.ProCSharp.IBankAccount'</span></p>
<h3 style="MARGIN: 8.15pt 0cm"><span lang="EN-US">4.4.2 </span><span style="FONT-FAMILY: 黑体">派生的接口</span></h3>
<p class="MsoNormal"><span><span style="FONT-FAMILY: 宋体">接口可以彼此继承,其方式与类的继承相同。下面通过定义一个新接口</span><span lang="EN-US">ITransferBankAccount</span></span><span style="FONT-FAMILY: 宋体">来说明这个概念,该接口的功能与</span><span lang="EN-US">IBankAccount</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">namespace Wrox.ProCSharp</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 interface ITransferBankAccount : IBankAccount</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"> bool TransferTo(IBankAccount destination, decimal amount);</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">ITransferBankAccount</span><span style="FONT-FAMILY: 宋体">派生于</span><span lang="EN-US">IBankAccount</span><span style="FONT-FAMILY: 宋体">,所以拥有</span><span lang="EN-US">IBankAccount</span><span style="FONT-FAMILY: 宋体">的所有成员和它自己的成员。这表示执行</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">派生于</span><span lang="EN-US">)ITransferBankAccount</span><span style="FONT-FAMILY: 宋体">的任何类都必须执行</span><span lang="EN-US">IBankAccount</span><span style="FONT-FAMILY: 宋体">的所有方法和在</span><span lang="EN-US">ITransferBankAccount</span><span style="FONT-FAMILY: 宋体">中定义的新方法</span><span lang="EN-US">TransferTo()</span><span style="FONT-FAMILY: 宋体">。没有执行所有这些方法就会产生一个编译错误。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">注意,</span><span lang="EN-US">TransferTo()</span><span style="FONT-FAMILY: 宋体">方法为目标账户使用了</span><span lang="EN-US">IBankAccount</span><span style="FONT-FAMILY: 宋体">接口引用。这说明了接口的用途:在执行并调用这个方法时,不必知道转帐的对象类型,只需知道该对象执行</span><span lang="EN-US">IBankAccount</span><span style="FONT-FAMILY: 宋体">即可。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">下面演示</span><span lang="EN-US">ITransferBankAccount</span><span style="FONT-FAMILY: 宋体">;假定</span><span lang="EN-US">Planetary Bank of Jupiter</span><span style="FONT-FAMILY: 宋体">还提供了一个当前账户。</span><span lang="EN-US">CurrentAccount</span><span style="FONT-FAMILY: 宋体">类的大多数执行代码与</span><span lang="EN-US">SaverAccount </span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"> GoldAccount</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></p>
<p class="2" style="BACKGROUND: none transparent scroll repeat 0% 0%; MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">public class CurrentAccount : ITransferBankAccount</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> private decimal balance;</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> public void PayIn(decimal amount)</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US"> balance += amount;</span></p>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?