接口和抽象类该如何取舍
解答
接口和抽象类非常相似,两者都无法实例化,并且未实现部分都由派生类实现。
接口与抽象类的主要区别有以下几点
- 抽象类只能派生类,而接口可以派生类和结构。
- 抽象类的派生类也可以是抽象类,即抽象成员在派生类中不一定被完全实现。而接口要求其派生类或结构必须完全实现其成员。
- 抽象类可以包含己经实现的成员,可以包含字段,而接口只包含未实现的成员,不能包含字段。并且接口及所含成员必须为
public
访问级别。- 类只能继承一个抽象类,但可以继承(实现)多个接口。
在具体的程序设计中,抽象类和接口的取舍应视程序的需要而定。
- 抽象类可以用于归纳一组相似的、有共同特性的类,然后将这些类共同的成员提取到抽象类中,使抽象类作为这组类的基类。
- 这样做到了代码的复用,不但节约了代码量,也减轻了维护的复杂度,然后将这组类中相似的方法或属性提取到抽象类中,成为抽象类的抽象成员,不提供具体实现,由这组类自己完成不同的实现。
说明:抽象类的应用非常类似于网页制作中的CSS外部样式文件、大量风格相同的页面可以共用这个CSS文件,并且在页面中可以对部分CSS属性进行改写。
- 接口是一组类的功能集合,也可以说是一组类的协定集合,这组类负责实现这些功能,可以说接口内含的成员都是抽象的。
- 类可以实现多个接口,这样可将意图和实现分离,接口可以暴露给其他程序直接使用,并且可以很方便地进行功能的扩展。
分析
- 抽象类是一种用
abstract
关键字修饰的类,这种类仅用于被继承。类似于接口,抽象类无法创建实例,而类体可以声明多个未实现的抽象成员,这些成员由继承此类的派生类实现。 - 抽象类的类体中可包含实现的成员,而未实现的成员为抽象成员。
- 抽象方法或属性本身就是隐性的
virtual
,所以派生类实现抽象方法或属性必须使用override
关键字。 - 继承抽象类的类如果没有完全实现抽象成员,仍然只能是抽象类,即派生的非抽象类必须完全实现抽象成员。
- 抽象类也可以实现接口,这时抽象类必须实现所有的接口成员,也可以将继承的接口成员映射至抽象成员,并由其派生类来实现。
说明:抽象类的成员不能使用
virtaul
或static
修饰。
简述C#变量的隐式类型声明
解答
- C#提供了var关键字,用于隐式声明局部变量的数据类型,由编译器根据初始值推测具体的数据类型。
- var声明的变量是局部变量,只能用于声明方法或属性的变量声明,而且声明时必须对变量赋予非null的初始值。
分析
- C#中声明变量的方法和其他编程语言类似,一般需要声明其数据类型,完成变量的初始化工作。
- 在C#中,提供了
var
关键字以代替数据类型声明,编译器将在变量被赋初始值后判断其数据类型,并完成初始化的工作。 - 这种方法有点类似弱类型编程语言的变量声明方法。
如,JavaScript这些弱类型语言声明一个变量后,允许在作用域内存储不同数据类型的值。而C#是强类型语言,即便使用了
var
关键字同样没有质的变化,只是当编译器遇到var
时,将根据初始值推测出相应的数据类型设置为该变量的类型,如果在作用域内给变量赋予有别于这个数据类型的新值,则会产生编译错误。
- C#提供
var
关键字在一定程度上方便了编程者的变量声明,不过为了程序的可读性、可维护性,var
关键字不宜滥用。
简要地谈谈分部类型和分部方法
解答
- 在.NET程序开发中,集成开发环境经常自动生成大量类的代码,而编程者也要手工编写该类的代码。为了分离相同类的代码,C#提供了
partial
关键字可将同一个类型编写于多个文件中,这种类型被称为分部类型。 - 在C#中,可以使用
partial
关键字定义分部方法,其目的和分部类型类似,不过分部方法所受限制更多。
分析
- C#很早就提供了
partial
关键字,中文意思是局部的、部分的,该关键字主要用于修饰类型。 - 在程序开发中,类型一般需定义在一个文件中,当类体的内容过多时影响其可读性、可维护性。而
partial
修饰的类型(即分部类型)允许在多个文件中编写同一个类的类体,只是在编译后才成为一个不可分的类型。 - 分部类型的出现可将复杂的类型分离为多个部分,极大地方便了团体合作项目的便利性,同时也有利于相同类中集成开发环境自动生成的代码和用户编写的代码分开存储。
- C#中也提供了分部方法,即将
partia
l关键字用于修饰类中的方法。
虽然分部方法的概念和分部类型的概念有很多相似之处,但有其特殊性,不可任意定义,须遵从以下限制
- 分部方法可以是静态方法,但必须是隐式的私有方法,并且是无返回值的方法。
说明:由于分部方法是私有方法,所以无法使用virtual
修饰符,即不能成为虚方法。)- 分部方法只能将方法分为两部分,即声明部分和实现部分。
- 分部方法只用于分部类型,方法的声明部分和实现部分可位于分部类型的不同部分。
- 分部方法可以有
ref
参数,但不能有out
参数。- 不允许将委托转换为分部方法。