练习

  (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
        }
    }

  这些代码会循环下去,因为同花色是不常见的。可能需要按几次回车键,才能在洗好的扑克牌中找到一个同花色。为了验证一切如期执行,可以尝试将洗牌的代码行注释掉。

🔚