⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 123456.txt

📁 c#编程入门,我在其它网站收集的."功能描述要求的字数太多能不能少一点"
💻 TXT
📖 第 1 页 / 共 5 页
字号:
((BaseClass)DerivedClassInstance).CanBOverridden();  
       为了演示虚拟方法的概念,清单 5.4 显示如何创建一个三角形基类,它拥有一个可以被改写的成员方法  
(ComputeArea)。  

清单 5.4   改写一个基类的方法  

1: using System;  
2:   
3: class Triangle  
4: {  
5:  public virtual double ComputeArea(int a, int b, int c)  
6:  {  
7:   // Heronian formula  
8:   double s = (a + b + c) / 2.0;  
9:   double dArea = Math.Sqrt(s*(s-a)*(s-b)*(s-c));  
10:   return dArea;  
11:  }  
12: }  
13:   
14: class RightAngledTriangle:Triangle  
15: {  
16:  public override double ComputeArea(int a, int b, int c)  
17:  {   
18:   double dArea = a*b/2.0;  
19:   return dArea;  
20:  }  
21: }  
22:   
23: class TriangleTestApp  
24: {  
25:  public static void Main()  
26:  {  
27:   Triangle tri = new Triangle();  
28:   Console.WriteLine(tri.ComputeArea(2, 5, 6));  
29:     
30:   RightAngledTriangle rat = new RightAngledTriangle();  
31:   Console.WriteLine(rat.ComputeArea(3, 4, 5));  
32:  }  
33: }  

    基类Triangle定义了方法ComputeArea。它采用三个参数,返回一个double结果,且具有公共访问性。从Triangle类派  
生出的是RightAngledTriangle,它改写了ComputeArea 方法,并实现了自己的面积计算公式。两个类都被实例化,且在命  
名为TriangleTestApp的应用类的Main() 方法中得到验证。  
我漏了解释第14行:  
class RightAngledTriangle : Triangle  
    在类语句中冒号(:)表示RightAngledTriangle从类 Triangle派生。那就是你所必须要做的,以让C#知道你想把   
Triangle当作RightAngledTriangle的基类。  
     当仔细观察直角三角形的ComputeArea方法时,你会发现第3个参数并没有用于计算。但是,利用该参数就可以验证是  
否是“直角”。如清单5.5所示。  

清单 5.5   调用基类实现  

1: class RightAngledTriangle:Triangle  
2: {  
3:  public override double ComputeArea(int a, int b, int c)  
4:  {  
5:   const double dEpsilon = 0.0001;  
6:   double dArea = 0;  
7:   if (Math.Abs((a*a + b*b - c*c)) > dEpsilon)  
8:   {  
9:    dArea = base.ComputeArea(a,b,c);  
10:   }  
11:   else  
12:   {  
13:    dArea = a*b/2.0;  
14:   }  
15:   
16:   return dArea;  
17:  }  
18: }  

  该检测简单地利用了毕达哥拉斯公式,对于直角三角形,检测结果必须为0。如果结果不为0,类就调用它基类的   
ComputeArea来实现。  
dArea = base.ComputeArea(a,b,c);  
  例子的要点为:通过显式地利用基类的资格检查,你就能轻而易举地调用基类实现改写方法。  
当你需要实现其在基类中的功能,而不愿意在改写方法中重复它时,这就非常有帮助。  

5.2.3 方法屏蔽  
    重定义方法的一个不同手段就是要屏蔽基类的方法。当从别人提供的类派生类时,这个功能特别有价值。看清单   
5.6,假设BaseClass由其他人所写,而你从它派生出 DerivedClass 。  

清单 5.6   Derived Class 实现一个没有包含于 Base Class中的方法  

1: using System;  
2:   
3: class BaseClass  
4: {  
5: }  
6:   
7: class DerivedClass:BaseClass  
8: {  
9:  public void TestMethod()  
10:  {  
11:   Console.WriteLine("DerivedClass::TestMethod");  
12:  }  
13: }  
14:   
15: class TestApp  
16: {  
17:  public static void Main()  
18:  {  
19:   DerivedClass test = new DerivedClass();  
20:   test.TestMethod();  
21:  }  
22: }  

    在这个例子中, DerivedClass 通过TestMethod()实现了一个额外的功能。但是,如果基类的开发者认为把  
TestMethod()放在基类中是个好主意,并使用相同的名字实现它时,会出现什么问题呢?(见清单5.7)  

清单 5.7    Base Class 实现和 Derived Class相同的方法  

1: class BaseClass  
2: {  
3:  public void TestMethod()  
4:  {  
5:   Console.WriteLine("BaseClass::TestMethod");  
6:  }  
7: }  
8:   
9: class DerivedClass:BaseClass  
10: {  
11:  public void TestMethod()  
12:  {  
13:   Console.WriteLine("DerivedClass::TestMethod");  
14:  }  
15: }  

在优秀的编程语言中,你现在会遇到一个真正的大麻烦。但是,C#会给你提出警告:  
hiding2.cs(13,14): warning CS0114: ’DerivedClass.TestMethod()’ hides inherited member ’BaseClass.TestMethod  
()’. To make the current method override that implementation, add the override keyword. Otherwise add the   
new keyword.  
(hiding2.cs(13,14):警告  CS0114:’DerivedClass.TestMethod()’ 屏蔽了所继承的成员’BaseClass.TestMethod()’。要  
想使当前方法改写原来的实现,加上 override关键字。否则加上新的关键字。)  
具有了修饰符new,你就可以告诉编译器,不必重写派生类或改变使用到派生类的代码,你的方法就能屏蔽新加入的基类方  
法。清单5.8  显示如何在例子中运用new修饰符。  

清单  5.8   屏蔽基类方法  

1: class BaseClass  
2: {  
3:  public void TestMethod()  
4:  {  
5:   Console.WriteLine("BaseClass::TestMethod");  
6:  }  
7: }  
8:   
9: class DerivedClass:BaseClass  
10: {  
11:  new public void TestMethod()  
12:  {  
13:   Console.WriteLine("DerivedClass::TestMethod");  
14:  }  
15: }  

使用了附加的new修饰符,编译器就知道你重定义了基类的方法,它应该屏蔽基类方法。但是,如果你按以下方式编写:  
DerivedClass test = new DerivedClass();  
((BaseClass)test).TestMethod();  
  基类方法的实现就被调用了。这种行为不同于改写方法,后者保证大部分派生方法获得调用。


5.3  类属性  
    有两种途径揭示类的命名属性——通过域成员或者通过属性。前者是作为具有公共访问性的成员变量而被实现的;后者并不直接回应存储位置,只是通过 存取标志(accessors)被访问。  
    当你想读出或写入属性的值时,存取标志限定了被实现的语句。用于读出属性的值的存取标志记为关键字get,而要修改属性的值的读写符标志记为set。  
在你对该理论一知半解以前,请看一下清单5.9中的例子,属性SquareFeet被标上了get和set的存取标志。  
清单 5.9  实现属性存取标志  

1: using System;  
2:   
3: public class House  
4: {  
5:  private int m_nSqFeet;  
6:   
7:  public int SquareFeet  
8:  {  
9:   get { return m_nSqFeet; }  
10:   set { m_nSqFeet = value; }  
11:  }  
12: }  
13:   
14: class TestApp  
15: {  
16:  public static void Main()  
17:  {  
18:   House myHouse = new House();  
19:   myHouse.SquareFeet = 250;  
20:   Console.WriteLine(myHouse.SquareFeet);  
21:  }  
22: }  

    House类有一个命名为SquareFeet的属性,它可以被读和写。实际的值存储在一个可以从类内部访问的变量中——如果  
你想当作一个域成员重写它,你所要做的就是忽略存取标志而把变量重新定义为:  
public int SquareFeet;  
对于一个如此简单的变量,这样不错。但是,如果你想要隐藏类内部存储结构的细节时,就应该采用存取标志。在这种情  
况下,set 存取标志给值参数中的属性传递新值。(可以改名,见第10行。)  
除了能够隐藏实现细节外,你还可自由地限定各种操作:  
get和set:允许对属性进行读写访问。  
get only:只允许读属性的值。  
set only:只允许写属性的值。  
除此之外,你可以获得实现在set标志中有效代码的机会。例如,由于种种原因(或根本没有原因),你就能够拒绝一个新  
值。最好是没有人告诉你它是一个动态属性——当你第一次请求它后,它会保存下来,故要尽可能地推迟资源分配。  

5.4   索引  
   你想过象访问数组那样使用索引访问类吗 ?使用C#的索引功能,对它的期待便可了结。  

语法基本上象这样:  
属性   修饰

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -