练习
(1)编写代码,定义一个基类 MyClass
,其中包含虚拟方法 GetString()
。这个方法应返回存储在受保护字段 myString
中的字符串,该字段可以通过只写公共属性 ContainedString
来访问。
答案:
class MyClass
{
protected string myString;
public string ContainedString
{
set
{
myString = value;
}
}
public virtual string GetString()
{
return myString;
}
}
(2)从类 MyClass
中派生一个类 MyDerivedClass
。重写 GetString()
方法,使用该方法的基类实现代码从基类中返回一个字符串,但在返回的字符串中添加文本 “(output from derived class)”。
答案:
class MyDerivedClass : MyClass
{
public override string GetString()
{
return base.GetString() + " (output from derived class)";
}
}
(3)部分方法定义必须使用 void
返回类型。说明其原因。
答案: 如果方法具有返回类型,就可以将其用作表达式的一部分:
x = Manipulate(y, z);
如果没有给部分方法提供实现代码,编译器就会在使用该部分方法的所有地方删除该方法。在上面的代码中,这会使x的结果变得模糊,因为Manipulate()方法没有替代方法。如果没有这个方法,可能只需忽略整行代码,但编译器无法确定我们是否的确希望忽略它。 没有返回类型的方法不能作为表达式的一部分来调用,所以编译器可以安全地删除对部分方法调用的所有引用。 同样,也禁止使用out参数,因为在方法调用之前,用作out参数的变量必须是未定义的,而应在方法调用之后定义。而应在方法调用之后定义。删除方法定义会违反这个规则。
(4)编写一个类 MyCopyableClass
,该类可以使用方法 GetCopy()
返回它本身的一个副本。这个方法应使用派生于 System.Object 的 MemberwiseClone()
方法。给该类添加一个简单的属性,并且编写客户代码,客户代码使用该类检查任务是否成功执行。
答案:
class MyCopyableClass
{
protected int myInt;
public int ContainedInt
{
get
{
return myInt;
}
set
{
myInt = value;
}
}
public MyCopyableClass GetCopy()
{
return (MyCopyableClass)MemberwiseClone();
}
}
客户端代码:
class Program
{
static void Main(string[] args)
{
MyCopyableClass obj1 = new MyCopyableClass();
obj1.ContainInt = 5;
MyCopyableClass obj2 = obj1.GetCopy();
obj1.ContainedInt = 9;
Console.WriteLine(obj2.ContainedInt);
}
}
这些代码显示5,说明所复制对象有自己专用的myInt字段。
(5)为 Ch10CardLib
库编写一个控制台客户程序,从洗牌后的 Deck
对象中一次取出 5 张牌。如果这 5 张牌都是相同花色,客户程序就应在屏幕上显示这 5 张牌,以及文本 "Flush!",否则在取出 50 张牌以后就输出文本 “No flush”,并退出。
答案:
using System;
using Ch10CardLib;
namespace Exercise_Answers
{
class Class1
{
static void Main(string[] args)
{
while(true)
{
Deck playDeck = new Deck();
playDeck.Shuffle();
bool isFlush = false;
int flushHandIndex = 0;
for(int hand = 0; hand < 10; hand++)
{
ifFlush = true;
Suit flushSuit = playDeck.GetCard(hand 5).suit;
for(int card = 1; card < 5; card++)
{
if(playDeck.GetCard(hand 5 + card).suit != flushSuit)
{
isFlush = false;
}
}
if(isFlush)
{
flushHandIndex = hand * 5;
break;
}
}
if(isFlush)
{
Console.WriteLine("Flush!");
for(int card = 0; card < 5; card++)
{
Console.WriteLine(playDeck.GetCard(flushHandIndex + card));
}
}
else
{
Console.WriteLine("No flush.");
}
Console.ReadLine();
}// end while
}// end Main
}
}
这些代码会循环下去,因为同花色是不常见的。可能需要按几次回车键,才能在洗好的扑克牌中找到一个同花色。为了验证一切如期执行,可以尝试将洗牌的代码行注释掉。