打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
.NET面试笔试中的对象

http://book.51cto.com/art/201009/224017.htm

第4章  面向对象程序设计

本章覆盖了.NET面试笔试中的对象、事件和委托等方面的题目。这一类题目属于实战类问题,涉及的知识点在面试中经常会出现,但有不少程序员无法正确回答此类问题。建议读者在实际研发的过程中,多多反思本章列出的各类题目,以期加强对这些问题的理解。

4.1  对象(1)

C#是主流的面向对象编程语言之一,它不仅语法简洁优美,而且它完美地支持面向对象的封装、继承和多态,在使用面向对象编程语言开发之前,笔者提倡先了解掌握面向对象的编程思想。在本节中,将集中讲解覆盖.NET面试中和面向对象思想有关的面试题。本节也是比较重要的章节之一,希望读者能认真阅读本章节的内容。

面试题46  类和结构有什么区别

这是一个关于C#语法的面试题,了解和记住这样的语法并不困难。但建议读者在得知答案后反复推敲类和结构的特性,充分掌握它们的特性。

【出现频率】★★★★★

【关键考点】

结构

【考题分析】

在C#中,类是功能最为强大的数据类型,类定义了数据类型的数据和行为。程序员可以创建类的实例对象。下面代码展示了一个标准的C#类。

  1. public class MyClass  
  2. {  
  3.     public string name;                 //定义字段  
  4.     public MyClass()                        //构造方法  
  5.     {  
  6.         name = "unknown";  
  7.     }  
  8.     public void SetName(string newName) //无返回值的普通方法  
  9.     {  
  10.         name = newName;  
  11.     }  

C#中的结构是使用struct关键字进行定义的,结构是值类型。下面代码展示了一个标准的C#结构。

  1. public struct Book                      //定义一个结构  
  2. {  
  3.     /*定义结构中的成员变量*/  
  4.     public decimal price;  
  5.     public string title;  
  6.     public string author;  

结构与类有以下3个方面的区别

结构是值类型,而类是引用类型。

结构不能被另外一个结构或者类继承,自身也不能被继承。而类完全可以被其他的类继承,其自身也能被继承。

结构没有默认的构造函数,也没有析构函数,并且不能有protected修饰符,但可以不使用new进行初始化。而类有默认的构造函数,也有析构函数,还有protected修饰符,并且必须使用new进行初始化。

注意:结构不能直接被类或结构继承,但结构能够继承接口。

【答案】

虽然结构与类的初始化都能使用new操作符,但它们之间的差别较大,主要体现在3个方面:结构是值类型,而类是引用类型;结构不能被继承而类可以;结构与类的内部结构不同。

面试题47  简述C#中的虚方法

C#中的虚方法是最常见的考题之一,应聘者需对这个题目做好充分的准备。本小节将介绍这方面的知识。

【出现频率】★★★★★

【关键考点】

虚方法(virtual)

虚方法的实现

【考题分析】

使用virtual关键字修饰的方法就是虚方法。下面展示一段标准的C#虚方法的实现。

  1. public class contact                    //定义contact类  
  2. {  
  3.     public virtual string print()       //用关键字virtual定义一个虚方法  
  4.     {  
  5.         return ("这是虚方法");  
  6.     }  
  7. }  
  8. public class MyClass : contact          //继承contact类  
  9. {  
  10.     public override string print()      //重写基类的print()方法  
  11.     {  
  12.         return ("这是新的方法");  
  13.     }  
  14. }  
  15. public static void Main()  
  16. {  
  17.     MyClass m = new MyClass();          //初始化MyClass()方法  
  18.     Console.WriteLine(m.print());       //调用print()方法  
  19.     Console.Read();  

在上面的代码中,基类contact定义了一个虚方法print(),而子类里也定义了一个用override 关键字修饰的print()方法。当笔者在主程序中调用子类的print()时,程序输出的结果是:

  1. 这是新的方法 

可以通过运行结果进行分析,程序调用的是子类的print()方法,而不是基类的print()方法,说明override关键字的作用是覆盖基类的虚方法。当然程序员也可以注销子类中的print()方法,再次运行上面的代码,程序输出结果是:

  1. 这是虚方法 

此次程序调用的是基类print方法,说明虚方法提供了实现部分,当子类没有重载基类的方法,默认调用的就是基类方法中的实现部分。

注意:当使用virtual关键字修饰符后,不允许再同时使用abstract、static或override关键字进行修饰。

【答案】

使用virtual关键字修饰的方法就是虚方法,虚方法(virtual)的关键字用于修饰属性、方法、索引器或事件声明,并使它们可以在派生类中被重写。虚方法必须并提供派生类覆盖该方法的选项,并且必须有实现部分。虚方法的作用是可以在派生类中被重写。

 

4.1  对象(2)

面试题48  简述C#中的密封类和密封方法

C#中的密封类和密封方法是一个语法类的面试题,也是最常见的考题之一。本小节将重点介绍这方面的知识。

【出现频率】★★★★★

【关键考点】

密封类

密封方法

【考题分析】

密封类使用sealed关键字进行修饰,它不能用作其他类的基类,并且它没有派生类。下面是一段简单的实例代码。

  1. class A {}                  //定义一个普通的class  
  2. sealed class B : A {}       //定义密封类  
  3. class C : B {}              //下面是错误的代码,
    密封类是不能够被其他类型继承 

密封方法(sealed)是使用sealed关键字进行修饰的方法,它并不影响类的继承,但它可以防止重写基类中特定的虚方法。下面是一段简单的实例代码。

  1. class A  
  2. {  
  3.     protected virtual void F() { Console.
    WriteLine("A.F");}//定义一个虚方法  
  4. }  
  5. class B : A  
  6. {  
  7.     sealed protected override void F() {
    Console.WriteLine("B.F");}  
  8.                                                     
    //定义密封方法  
  9. }  
  10. class C : B  
  11. {  
  12.     //下面是一段错误的代码,密封方法不能够重写  
  13.     protected override void F() { Console.WriteLine("C.F"); }  

【答案】

密封类使用sealed关键字进行修饰,它不能用作其他类的基类,并且它没有派生类。密封类的作用是防止其他类继承该类。密封方法是使用sealed关键字进行修饰的方法,它并不影响类的继承,但它可以防止重写基类中特定的虚方法。

面试题49  请介绍C#中静态类构造方法的特点

C#中静态类构造方法及特点是一道常见的面试题,静态类构造是很有用的一个功能,程序员应该掌握这方面的应用。本小节将简单地介绍静态类中的构造方法。

【出现频率】★★★★★

【关键考点】

静态类

构造方法

构造方法的特点

【考题分析】

构造方法是一种特殊的方法,一般用于初始化对象,并且在类实例化之前执行,用于完成对象创建前所需的相关设定。构造方法也称为构造函数,只要创建类或结构,就会调用它的构造函数。类或结构可能有多个接收不同参数的构造函数。

下面的示例代码展示了一个构造方法。

  1. class StaticSimple  
  2. {  
  3.     public static int k =100;               //定义静态变量  
  4.     static StaticSimple()                   //创建
    自定义的静态构造方法  
  5.     {  
  6.         Console.WriteLine("请注意方法的执行顺序。");  
  7.     }  
  8.     //注释的这段代码是错误的代码,在一个类里只允许有一
    个无参的静态构造方法  
  9.     //static StaticSimple(String str)  
  10.     //{  
  11.     //  Console.WriteLine("在一个类里只允许有一个
    无参的静态构造方法。");  
  12.     //}  
  13.     public StaticSimple()               //定义无
    参的构造器,同时给j和s赋值  
  14.     {  
  15.         Console.WriteLine("这是无参构造器");  
  16.     }  
  17. }  
  18. class Program  
  19. {  
  20.     static void Main(string[] args)  
  21.     {  
  22.     //先调用静态成员k的值,结果会是先执行静态构造方
    法,再显示
    k=100 
  23.     Console.WriteLine("读者请注意,在输入k值请是
    否有其他的输出。
    k=" + Static  
  24.     Simple.k);  
  25.     //此时不会再出现static构造器的内容,因为前面已经执行了一次  
  26.     StaticSimple A = new StaticSimple();  
  27.     Console.Read();  
  28.     }  

通过运行上面的代码可以发现,C#中的构造方法有以下4个特点。

只允许有一个无参的静态构造方法在一个类中存在。

静态的构造方法不会被继承。

在所有静态成员被引用之前执行静态构造方法。

在所有的构造方法中最先被执行的是静态的构造方法。

说明:静态构造方法,是在构造方法的名字前使用static关键字修饰符的构造方法。

【答案】

C#中静态类构造方法主要有4大特点,静态构造方法最主要的特点是:静态的构造方法是最先被执行的构造方法,并且在一个类里只允许有一个无参的静态构造方法。

4.1  对象(3)

面试题50  简述C#派生类中的构造函数

这个问题是一道基础的面试题,主要考察应聘者对派生类和构造方法的概念。本小节将简单地介绍派生类与构造方法。

【出现频率】★★★★

【关键考点】

派生类

构造方

【考题分析】

派生类中的对象不但包含从基类继承的成员对象,也包含了局部定义的成员对象。这时会出现一个问题:基类中有一部分构造函数,而在派生类中也有一些构造函数,当创建派生类对象时,到底运行的是那些构造函数呢?带着这个问题先看下面一段代码。

  1. class Circle  
  2. {  
  3.     public Circle()                         //默认构造函数  
  4.     {  
  5.         Console.WriteLine("基类无参构造方法。");  
  6.     }  
  7.     public Circle(double initialRadius) //带一个参数的构造函数  
  8.     {  
  9.         Console.WriteLine("基类有参构造方法。");  
  10.     }  
  11. }  
  12. class UnitCircle : Circle                   //派生类  
  13. {  
  14.     public UnitCircle(double unitRadius) :base(unitRadius) {}  
  15.                                             //调用基类的构造函数  
  16.     public UnitCircle():this(1,2)           //调用本类中的构造函数  
  17.     {  
  18.         Console.WriteLine("派生类无参构造方法。");  
  19.     }  
  20.     public UnitCircle(int i,int j)          //定义
    一个带两个参数的构造函数  
  21.     {  
  22.         Console.WriteLine("派生类有参构造方法。"+i.ToString());  
  23.     }  
  24. }  
  25. class Program  
  26. {  
  27.     static void Main(string[] args)  
  28.     {  
  29.             UnitCircle u = new UnitCircle();    //调用
    派生类中的无参构造函数  
  30.         UnitCircle u1 = new UnitCircle(2);  
  31.                                         //调用派
    生类中的有一个参数的构造函数  
  32.         Console.Read();  
  33.     }  

运行上面的代码,请读者注意base与this这两个关键字的作用:

  1. public UnitCircle(double unitRadius) :base(unitRadius) {} 

派生类中的base关键字表示当调用UnitCircle(double unitRadius)构造函数时,它实际调用的是基类中的Circle(double initialRadius)构造函数。

而派生类中的this关键字表示当调用的构造函数,是本派生类中的构造函数。

  1. public UnitCircle():this(1,2) 

【答案】

使用C#派生类中的构造函数时,需要注意关键字base与this的区别,关键字base表示调用基类中的构造函数,而this表示调用本类中的构造函数。

面试题51  简述接口及接口继承

在大多数面向对象的语言中,都有接口这个概念,这些机制是设计高可扩展性的面向对象程序的基础。读者应该做到不仅了解它们的功能、读懂包含这些概念的代码,也能进一步地运用它们设计出面向对象的程序。

【出现频率】★★★★★

【关键考点】

接口(Interface)

接口特性

接口继承

【考题分析】

接口是面向对象编程思想重要特性之一,接口是当把多个继承类中的公共对象部分抽象出来、并封装这些公共对象的行为。接口是为了继承而存在的,如果没有继承,也就不需要接口的存在。

注意:在C#中,类可以通过继承多个接口来丰富自己的行为机制,但类是不可以继承多个类的。

在C#中,接口具有以下9大特性。

接口只定义,不包含方法的实现。

接口可以包含方法、属性、事件和索引器。

接口成员必须是公共的。

接口不能被直接实例化。

接口不能包含任何字段。

接口描述可属于任何类或结构的一组相关行为。

接口自身均可以从多个接口继承。

类和结构均可以从多个接口继承。

接口类似于抽象类,但继承接口的类型必须实现接口中的所有定义的成员对象。

下面代码实现了一个简单的信号灯功能,代码如下:

  1. interface ITrafficRule                      //定义
    一个接口(交通规则)  
  2. {  
  3.    void CrossTheRoad(int trafficLight);     //定义
    一个方法(十字路口)  
  4. }  
  5. public class MyPupil : ITrafficRule  
  6. {  
  7.     public void CrossTheRoad(int trafficLight)  
  8.                                             //实现
    十字路口的信号灯功能的方法  
  9.     {  
  10.         switch (trafficLight)  
  11.         {  
  12.         case 0:                             //红灯停  
  13.         …  
  14.         break;  
  15.         case 1:                             //黄灯等一等  
  16.          …  
  17.         break;  
  18.         case 2:                             //绿灯行  
  19.         …  
  20.         break;  
  21.         default:                //当信号故障,且
    两侧没有直行车辆时,可以穿过马路  
  22.         …  
  23.         break;  
  24.         }  
  25.     }  

在代码中,笔者首先定义了一个信号灯规则的接口,随后在接口中定义了一个实现信号的方法。代码如下:

  1. interface ITrafficRule  
  2. {  
  3.     void CrossTheRoad(int trafficLight);        
    //定义一个方法(十字路口)  

注意:在笔者定义的接口中仅仅是声明定义了一个方法,并没有任何代码功能的实现。信号灯功能的实现是在它的继承类MyPupil中实现。结合前面对接口及接口继承的特性的说明,就不难理解这段实例代码。

【答案】

接口是把隐式公共方法和属性组合起来,以封装特定功能的一个集合。当定义了接口,就必须在继承类中实现它,这样类就支持接口中所指定的所有属性和成员。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C#Static类和Static构造函数
C#基础到入门(一篇就够了)
C# 类的构造函数 解析
C#基础方法和要点
接口与抽象类的异同
静态变量与非静态变量的区别
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服