引用:
C#首席架构师:版本控制、虚拟化和覆盖
网址:http://www.csdn.net/article/2012-09-17/2810048-Anders-Hejlsberg-on-Versioning-Virtual-O
Bill
Venners:在Java中,实例方法默认是虚拟化的,只有显式声明为final时,才可以在子类中被覆盖。相比之下,C#中实例方法默认为非虚拟化,要想声明虚拟化方法需要显式声明它为虚拟的。为什么要这样做?
Anders Hejlsberg:原因在于以下几点:
首先是性能。通过观察,我们发现用Java程序员在写代码时常常会忘记将方法声明为final,因此这些方法将是虚拟化的,所以性能并不好。相比于使用虚拟方法这样会带来性能上的提升。这是其一。
更重要的一点在于版本控制。关于虚拟方法主要有两派思想:一是学院派,他们认为“任何事物都应该是虚拟化的,因为我可能会在将来覆盖它”;务实派(从现实世界中获取开发应用的思路)认为“我们只需要关心有必要的虚拟化”。
当我们将平台中某物虚拟化时,对未来的变化做了过多的假设和保留。对于一个非虚拟化的方法,在你调用它时会发生x、y;而在API中发布一个虚拟化的方法时,不仅在你调用该方法时会发生x、y。我们同样保证当你在覆盖这个方法时,会在这个特定的序列中调用它,注意到这些状态不变条件。
每当使用到API中的虚拟化时,你就是在创造一个回调的hook。作为一个OS或者API框架设计师,更需要注意这些。你不会希望用户在API任何部分重载和hook,因为你不一定能保证这些。同样,人们在虚拟化声明某物时也并不一定完全了解他们自己做的保证。
C# 语言经过专门设计,以便不同库中的基类与派生类之间的版本控制可以不断向前发展,同时保持向后兼容。这具有多方面的意义。例如,这意味着在基类中引入与派生类中的某个成员具有相同名称的新成员在 C# 中是完全支持的,不会导致意外行为。它还意味着类必须显式声明某方法是要重写一个继承方法,还是一个隐藏具有类似名称的继承方法的新方法。
在 C# 中,派生类可以包含与基类方法同名的方法。
-
基类方法必须定义为 virtual。
-
如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在 new 关键字一样执行操作。
-
如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。
-
如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。
-
可以从派生类中使用 base 关键字调用基类方法。
-
override、virtual 和 new 关键字还可以用于属性、索引器和事件中。
new 关键字:
class Father
{
public int getInt()
{
Console.WriteLine("Father: getInt()");
return 2;
}
public int setInt()
{
Console.WriteLine("Father: setInt()");
return 3;
}
}
//---------------------------------------------------------------------
class Son : Father
{
public new int getInt()
{
Console.WriteLine("Son: getInt()");
return 1;
}
}
//-------------------测试----------------------------------------------------
class Program
{
static void Main(string[] args)
{
Father fs = new Son();
Console.WriteLine(fs.getInt());
Console.WriteLine(fs.setInt());
Console.WriteLine("--------------------------------------------------------");
Son fs2 = new Son();
Console.WriteLine(fs2.getInt());
Console.WriteLine(fs2.setInt());
Console.ReadLine();
}
}
输出结果:
Father: getInt()
2
Father: setInt()
3
----------------------------------------------
Son: getInt()
1
Father: setInt()
3
Virtural 与 Override 关键字
class Father {
public int getInt()
{
Console.WriteLine("Father: getInt()");
return 2;
}
virtual public int setInt()
{
Console.WriteLine("Father: setInt()");
return 3;
}
}
class Son : Father
{
public new int getInt()
{
Console.WriteLine("Son: getInt()");
return 1;
}
public override int setInt()
{
Console.WriteLine("Son: setInt()");
return 4;
}
}
class Program
{
static void Main(string[] args)
{
Father fs = new Son();
Console.WriteLine(fs.getInt());
Console.WriteLine(fs.setInt());
Console.WriteLine("--------------------------------------------------------");
Son fs2 = new Son();
Console.WriteLine(fs2.getInt());
Console.WriteLine(fs2.setInt());
Console.ReadLine();
}
}
/*
输出结果:
Father: getInt()
2
Son: setInt()
4
----------------------------------------------
Son: getInt()
1
Son: setInt()
4
*/
-
接口中,子类显示实现接口,则为接口调用
-
隐式实现接口,则为类自己调用
public interface IReview {
void GetReviews();
}
public class ShopReview :IReview {
public void GetReviews(){}
}
//这种方式是隐示实现:
IReview rv = new ShopReview();rv.GetReviews();
ShopReview rv = new ShopReview();rv.GetReviews();
//都可以调用GetReviews这个方法。
//还有一种方式是显示实现:
public interface IReview {
void GetReviews();
}
public class ShopReview :IReview {
void IReview.GetReviews(){}
}
//通过这种方式的接口实现。
//GetReviews就只能通过接口来调用:
IReview rv = new ShopReview();rv.GetReviews();
//下面的这种方式将会编译错误
ShopReview rv = new ShopReview();rv.GetReviews();
/*
结论:
隐示实现接口和类都可以访问
显示实现只有接口可以访问。
显示实现益处
1:隐藏代码的实现
2:在使用接口访问的系统中,调用者只能通过接口调用而不是底层的类来访问。
*/
默认情况下,C# 方法为非虚方法。如果某个方法被声明为虚方法,则继承该方法的任何类都可以实现它自己的版本。若要使方法成为虚方法,必须在基类的方法声明中使用 virtual 修饰符。然后,派生类可以使用 override 关键字重写基虚方法,或使用 new 关键字隐藏基类中的虚方法。如果 override 关键字和 new 关键字均未指定,编译器将发出警告,并且派生类中的方法将隐藏基类中的方法。
分享到:
相关推荐
第七章 表达式<br> 第八章 流程控制<br>第三部分 面向对象的C#<br> 第九章 面向对象的程序设计<br> 第十章 类<br> 第十一章 方法<br> 第十二章 域和属性<br> 第十三章 事件和索引指示器<br> 第十四章 继承<br>第四...
【标题】"C#面向对象编程期末参考题"揭示了本次讨论的核心——C#编程语言中的面向对象编程(Object-Oriented Programming, OOP)概念,这是软件开发中的一种重要方法论。C#是一种现代、类型安全且面向对象的语言,...
4. **面向对象编程**:类与对象的概念、继承、封装、多态性等面向对象特性。 ### Windows应用程序开发 1. **Windows Forms**:使用Windows Forms创建GUI应用程序的方法,包括控件使用、事件处理等。 2. **WPF...
二、面向对象编程 C#是严格意义上的面向对象语言,其三大特性——封装、继承和多态在书中会得到详尽解释。封装通过访问修饰符(public、private、protected等)实现数据隐藏;继承允许子类从父类继承属性和方法,...
"C#入门到精通"强调了一个完整的学习路径,包括基础语法(变量、控制流、数组、类和对象)、面向对象编程(继承、多态、封装)、异常处理、文件操作、集合和数据结构、数据库访问(ADO.NET)以及WPF、ASP.NET等UI...
在深入探讨C#面向对象编程的三大原则:封装...总之,C#面向对象编程的三大原则——封装、继承和多态,为软件设计和开发提供了强大的工具和指导思想。理解并熟练掌握这些原则,对于成为一名优秀的C#程序员至关重要。
而在C#编程中,面向对象编程(Object-Oriented Programming, OOP)是核心概念之一,它通过类、对象、封装、继承和多态等特性,使得代码更加模块化,易于维护和扩展。本项目以经典游戏“俄罗斯方块”为例,展示了如何...
C#中的类和对象是面向对象编程的核心,需要理解类的定义、对象的创建、封装、继承、多态等概念。 在C#中,函数和方法是实现程序功能的基本单元,学会如何定义、调用和传递参数至关重要。同时,C#提供了丰富的内置...
总结来说,本主题涉及了C#中的面向对象编程,主要集中在继承和多态这两个关键特性。通过Shape基类和其子类的实现,我们可以看到如何创建和使用具有不同特性的图形对象。同时,多态性的运用使得我们可以以统一的方式...
C#是微软为.NET Framework设计的面向对象的编程语言,具有类型安全、垃圾回收、异常处理等特性。在ASP.NET中,C#用于编写后台逻辑,控制页面行为,处理用户请求。掌握C#的关键概念,如类、对象、接口、继承、多态和...
1. 封装:这是面向对象编程的核心特性之一,它隐藏了对象内部的实现细节,只对外提供接口进行交互。这样可以保护数据不被外部随意访问,提高程序的安全性和稳定性。 2. 继承:继承允许一个类(子类)从另一个类...
由于文档内容存在扫描错误,导致部分文字无法辨识,但根据上下文,可以推断文档内容主要在讨论面向对象编程中类和对象的概念,以及C++、Java和C#中类的定义和使用。因此,本文的目的是解释面向对象编程中类和对象的...
面向对象编程(Object-Oriented Programming, OOP)是现代软件开发中的核心思想之一,它的主要特征包括封装、继承、多态和抽象。以下将详细解释这些概念及其在C#中的应用: 1. **封装**:封装是将数据和操作数据的...
2. **面向对象编程**:C#的类、对象、继承、多态、封装等面向对象概念是其核心特性。理解和掌握这些概念能帮助开发者设计出可维护、可扩展的代码结构。 3. **异常处理**:学习如何使用try-catch-finally语句块进行...
【标签】"c#,面向对象"再次强调了我们讨论的是C#语言中的面向对象编程技术。 【压缩包子文件的文件名称列表】: 1. "www.pudn.com.txt":这个文件可能包含从Pudn.com网站下载的关于C#面向对象编程的资料或者代码...
2. **类与对象**:C#是面向对象的语言,会讲解类的定义、对象的创建和使用,以及封装、继承和多态等面向对象的基本概念。 3. **数组与集合**:如何使用数组来存储和操作同类型的数据,以及更灵活的集合类如List<T>...
- **面向对象编程**:C#支持类、对象、继承、多态等面向对象编程特性。 #### 开发环境配置 - **Visual Studio 2010**:微软提供的集成开发环境,支持多种编程语言,包括C#。 - **IIS 7**:Internet Information ...
面向对象编程(Object-Oriented Programming,简称OOP)是现代软件开发中广泛采用的一种编程范式,它基于数据和操作这些数据的方法,强调通过类和对象来组织代码。C#语言是支持OOP概念的强大工具,常用于构建各种...
面向对象编程是现代软件开发的核心概念之一,尤其在C#这样的高级编程语言中,它提供了强大的工具和结构来创建高效、可维护的代码。本文将深入探讨C#2005中面向对象编程的基石——类和对象,通过解析给定文件的信息,...
首先,让我们深入理解面向对象编程的基础——类与对象。在C#中,类是创建对象的蓝图,它定义了对象的状态(数据成员,即属性)和行为(成员函数,即方法)。对象是类的实例,每个对象都有自己的状态和行为,它们可以...