多继承
如果要使用多继承,需要使用接口,因为C#中的类只支持单继承,而接口支持多继承,实现多继承时,继承的多个接口中间用逗号(,)隔开。
说明:
实现多继承时,继承的可以是多个接口,也可以是一个类及多个接口。
下面通过一个实例讲解如何实现多继承。
例创建一个控制台应用程序,首先定义两个接口,分别表示人的实体接口和行为接口;然后声明一个类,并使这个类继承于定义的两个接口,在该类中实现接口中的成员属性和方法;最后在Main方法中实例化派生类的对象,并使用该派生类对象调用人的实体接口和行为接口中的属性和方法。代码如下:
interface IPeopleEntity //定义一个实体接口
{
string Name //定义名字属性
{
get;
set;
}
}
interface IPeopleActive //定义一个行为接口
{
void say(string str); //定义说话方法
}
class PeopleClass:IPeopleEntity,IPeopleActive //继承定义的两个接口
{
string name = ""; //定义名字变量
public string Name //实现接口中定义的名字属性
{
get
{
return name;
}
set
{
name = value;
}
}
bool CheckChinese(string str) //定义一个方法,用来判断字符串是不是中文
{
bool flag = false; //定义一个bool类型变量,作为标识
UnicodeEncoding encode = new UnicodeEncoding(); //实例化编码对象
byte[] b = encode.GetBytes(str); //将字符串转换为字节数组
for (int i = 0; i < b.Length; i++) //遍历字节数组
{
if (b[i] != 0) //判断字节数组中指定索引处的值是不是0
{
flag = true; //设置标识为true
}
else
{
flag = false; //设置标识为false
}
}
return flag; //返回定义的标识
}
public void say(string str) //实现接口中定义的说话方法
{
if (CheckChinese(str)) //判断输入的是不是中文
{
Console.WriteLine(str+"是中国人,请说汉语!");
}
else
{
Console.WriteLine(str + " is a american,please speak english!");
}
}
}
class Program
{
static void Main(string[] args)
{
PeopleClass peopleclass = new PeopleClass(); //实例化类对象
while (true)
{
Console.Write("请输入名字:");
peopleclass.Name = Console.ReadLine(); //记录用户输入的名字
peopleclass.say(peopleclass.Name); //根据用户输入显示相应的字符串
}
}
}
继承的原则
上面详细讲解了如何实现继承,包括单继承和多继承,这里主要总结一下C#中实现继承的几个主要原则,分别如下:
q除了object类,每个类有且只有一个直接基类,如果没有显式指定类的直接基类,那么它的直接基类就隐含的设置为object。object类没有任何直接或间接基类,它是所有类的终极基类;
q无论基类成员的可访问性如何,除构造函数和析构函数外,所有其他基类的成员都能被子类继承,然而,有些继承成员在子类中可能是不可访问的,比如,基类的private成员在子类中不可访问,但是,如果将子类的对象作为参数传入基类的方法内,那么在基类的代码内部,就可以通过子类或者子类的对象来访问基类的private成员;
q子类可以扩展它的直接基类;
q继承是可以传递的,比如C类从B类继承,而B类从A类继承,那么C类就会既继承B类中的成员,又继承A类中的成员;
q类不能循环继承,比如A类继承于B类,而B类继承于C类,那么C类就不能再去继承A类,因为它们之间存在了一种循环关系;
q类的直接基类必须至少与类本身具有同样的可访问性,比如,如果从private类派生一个public类,将会导致编译时错误;
q在子类中可以声明具有相同名称或签名的新成员来隐藏从基类继承而来的成员,但是,隐藏继承而来的成员时并不移除该成员,而只是使被隐藏的成员在子类中不可以直接访问;
q类中可以声明虚方法等,而子类可以重写这些虚方法的实现;
qC#中只支持类的单一继承,但是支持接口的多重继承;
q类的实例包含在该类中及它的所有基类中声明的所有实例字段的集合,并且存在一个从子类到它的任何基类的隐式转换,因此,可以将子类的实例看成是其任何基类的实例的引用。
.net笔试题
答:C# 中的接口与类不同,可以使用多继承,即一个子接口可以有多个父接口。但如果两个父成员具有同名的成员,就产生了二义性,这时在实现时最好使用显式的声明
示例:
using System;
using System.Collections.Generic;
using System.Text;
namespace Example17
{
class program
{
//一个完整的接口声明示例
interface IExample
{
//属性
string p
{
get;
set;
}
//方法
string F(int Value);
//事件
event EventHandler E;
//索引指示器
string this[int Index]
{
get;
set;
}
}
interface IA
{
int Count { get; set;}
}
interface IB
{
int Count();
}
//IC接口从IA和IB多重继承
interface IC : IA, IB
{
}
class C : IC
{
private int count = 100;
//显式声明实现IA接口中的Count属性
int IA.Count
{
get { return 100; }
set { count = value; }
}
//显式声明实现IB接口中的Count方法
int IB.Count()
{
return count * count;
}
}
static void Main(string[] args)
{
C tmpObj = new C();
//调用时也要显式转换
Console.WriteLine("Count property: {0}", ((IA)tmpObj).Count);
Console.WriteLine("Count function: {0}", ((IB)tmpObj).Count());
Console.ReadLine();
}
}
}
结果:
Count property: 100
Count function: 10000