抽象类
一般将父类定义为抽象类,需要对父类进行继承和多态处理.
语法如下:
访问修饰符 abstract class 类名:基类或接口
抽象方法没有方法体,方法本身没有意义,除非被重写,承载这个方法的抽象类必须被继承,实际上抽象类除了被继承之外没有任何意义.
抽象类被继承后要实现其中所有的抽象方法,也就是保证相同的方法名称,参数列表和相同的返回类型创建出非抽象方法,也可以是抽象方法
图17.1可以看出,继承抽象类的所有子类需要将抽象类中的抽象方法覆盖。在多态中可以将父类设置为抽象类将draw()方法设置为抽象方法,然后每个子类都重写这个方法来处理.但这样会使程序产生太多冗余的代码,同时这样父类的局限性也很大,某个不需要draw()方法的子类也必须重写draw()方法.如果将draw()方法写入另一个类中,让那些需要draw的类继承该类,而不需要draw()的继承图型类,但所有的子类都需要图形类,因为这些类是从图形类中被导出的,同时某些类还需要draw()方法,但类不能同时继承多个父类,面临这种问题,接口会解决.
抽象方法概述及声明
1.抽象方法必须声明在抽象类中
2.声明抽象方法时,不能使用virtual,static和private修饰符
抽象方法声明引入一个新方法,但不提供该方法的实现,由于抽象方法不提供任何实现,因此抽象方法的方法体只包含一个分号.
当从抽象类派生一个非抽象类时,需要在非抽象类中重写抽象方法以提供具体的实现,重写抽象方法用override关键字
抽象类和抽象方法的使用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
public abstract class myclass
{
private string id = "";
private string name = "";
public string ID
{
get { return id; }
set { id = value; }
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public abstract void showinfo();//抽象方法,用来输出信息
}
public class DriveClass : myclass
{
public override void showinfo()
{
Console.WriteLine(ID + " " + Name);
}
}
class Program
{
static void Main(string[] args)
{
DriveClass dr = new DriveClass();//实例化派生类
myclass mc = dr;//使用派生类对象实例化抽象类
mc.ID = "45";
mc.Name = "yl";
mc.showinfo();//使用抽象类对象调用派生类中的方法
}
}
}
接口
使用接口可以实现多重继承的功能
接口是抽象类的延伸,可以将接口看作纯粹的抽象类,接口中所有方法都没有方法体.对于17.1图中的问题,可以将draw()方法封装到一个接口中。使需要draw()方法的类实现这个接口,同时也继承图形类,这就是接口存在的必要性.下图描述了各个子类继承图形类后使用接口的关系
接口的特征:
1.接口类似与抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员.
2.不能实例化接口
3.接口可以包含方法,属性,事件,索引器
4.接口不包含方法的实现
5.类和结构可以从多个接口继承
6.接口自身可以从多个接口继承
例:接口的实现与继承
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
interface myinter
{
string ID
{
get;
set;
}
string Name
{
get;
set;
}
void showInfo();//显示定义的编号和姓名
}
class Program:myinter
{
string id = "";
string name = "";
public string ID
{
get
{
return id;
}
set
{
id = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
static void Main(string[] args)
{
Program pr = new Program();
myinter mi = pr; //使用派生类对象实例化接口myinter
mi.Name = "yl";
mi.ID = "12";
mi.showInfo();//调用派生类中的方法显示定义的属性
}
public void showInfo()
{
Console.WriteLine(ID + " " + Name);
}
}
}
显示接口的成员实现
如果类实现两个接口,并且这两个接口包含具有相同签名的成员,那么在类中实现该成员将导致两个接口都使用该成员作为他们的实现.然而,如果两个接口成员实现不同的功能,则可能会导致其中一个接口的实现不正确或两个接口的实现都不正确,这时可以显示的实现接口成员,即创建一个仅通过该接口调用并且特定于该接口的类成员.显示接口成员的实现是使用接口名称和一个句号命名该成员实现的.
例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication6
{interface inter1
{
int add();
}
interface inter2
{
int add();
}
class Program:inter1,inter2
{ int inter1.add()
{
int x = 3; int y = 2;
return x + y;
}
int inter2.add()
{
int x = 3;int y = 3;int z = 2;
return x + y + z;
}
static void Main(string[] args)
{
Program pr = new Program();
inter1 in1 = pr;
Console.WriteLine(in1.add());
inter2 in2 = pr;
Console.WriteLine(in2.add());
}
}
}
显示接口成员实现中不能包含修饰符,abstract,virtual,override和static修饰符
显示接口不是类成员,因此不能使用类对象直接访问,只能通过接口对象访问.