1、继承
继承分为实现继承和接口继承
实现继承:新类型的定义是从已存在的基类型派生而来的,新类型拥有基类型的数据字段及函数。实现继承常用于需要为现有类添加新功能,或者是用于组织程序中的一组拥有相同功能的类型。
接口继承:新类型只能继承函数的签名,而不会包括函数的实现,这是由于接口中只能定义函数的签名。接口继承在需要指定一个类型必须拥有哪些特性时非常有用。
C#不允许一个内派生自多个基类,但是可以多接口继承。即C#的类能够派生自一个基类,并可以同时实现多个接口。
注:所有结构都自动派生自System.ValueType,但结构本身却不支持实现继承,所以在定义一个结构时不能为其制定基类,但是结构支持多接口继承。
2、实现继承
1、访问和隐藏基类的成员:若要隐藏基类的成员,则在派生类中声明相同的成员时要加上new修饰符。
实例如下:
class Person
{
public int Age { get; set; }
public string Name = "Person";
public void PrintInfo()
{
Console.WriteLine("=======Called Person.PrintInfo======");
Console.WriteLine("Name: {0}", Name);
Console.WriteLine("Age:{0}", Age);
}
}
class Worker : Person
{
new public string Name = "Worker"; //用new修饰符隐藏了继承自基类的成员
new public void PrintInfo()
{
Console.WriteLine("=======Called Worker.PrintInfo======");
Console.WriteLine("Name;{0}", Name);
Console.WriteLine("Age:{0}", Age);
}
}
class Customer : Person
{
public string Email { get; set; }
public string Phone { get; set; }
public void PrintExtraInfo()
{
Console.WriteLine("========Called CustomerInfo=======");
Console.WriteLine("Email:{0}", Email);
Console.WriteLine("Phone:{0}", Phone);
}
}
class Program
{
static void Main(string[] args)
{
Customer c = new Customer();
c.Age = 20;
c.Name = "John";
c.Email = "john@gmail.com";
c.Phone = "13456789878";
c.PrintInfo(); //访问基类的成员
c.PrintExtraInfo();
Worker w = new Worker();
w.Age = 20;
w.PrintInfo(); //隐藏了基类的成员,一定要加new才可隐藏
Console.WriteLine();
Person p = (Worker)w;
p.PrintInfo();
Console.ReadLine();
}
}
3、虚方法和多态性
虚方法的使用要注意以下几点:
- 基类和派生类中的方法必须具有相同的签名和返回值类型
- 基类中的方法被标记为virtual
- 派生类中的方法被标记为override
class Person
{
public int Age { get; set; }
public string Name = "Person";
public virtual void PrintInfo()
{
Console.WriteLine("=======Called Person.PrintInfo======");
Console.WriteLine("Name: {0}", Name);
Console.WriteLine("Age:{0}", Age);
}
}
class Worker : Person
{
public string Name = "Worker"; //用new修饰符隐藏了继承自基类的成员
public override void PrintInfo()
{
Console.WriteLine("=======Called Worker.PrintInfo======");
Console.WriteLine("Name;{0}", Name);
Console.WriteLine("Age:{0}", Age);
}
}
class Program
{
Worker w = new Worker();
w.Age = 20;
w.PrintInfo();
Console.WriteLine();
Person p = (Worker)w;
p.PrintInfo(); //由输出可知两次调用均为Worker类的方法,可与上述访问基类成员形成对比
Console.ReadLine();
}
}
输出结果:
4、抽象类和抽象方法
C#中可把类和函数声明为abstract,即抽象类,抽象类不能实例化,而抽象函数不包含实现,必须在非抽象的派生类中重写。也就是说,派生自抽象基类的类,如果本身不是抽象的,它就要实现在抽象类中声明的全部的抽象函数。如果类包含抽象函数,那么这个类必须声明为抽象类。
实例:
abstract class Person
{
public int Age { get; set; }
public string Name { get; set; }
public abstract void PrintInfo();
}
class Worker : Person
{
new public string Name = "Worker";
public override void PrintInfo()
{
Console.WriteLine("=======Called Worker.PrintInfo======");
Console.WriteLine("Name:{0}", Name);
Console.WriteLine("Age:{0}", Age);
}
}
class Program
{
static void Main(string[] args)
{
Worker w = new Worker();
w.Age = 22;
w.PrintInfo();
Console.WriteLine();
Person p = (Worker)w;
p.PrintInfo();
Console.ReadLine();
//Person p2 = new Person(); //此处错误,抽象类不可实例化
}
}
输出结果: