您的位置:首页 > 编程语言 > ASP

深入继承——抽象类和接口

2012-05-03 21:39 104 查看

一、基本概念一盘端

抽象类:又叫抽象基类:在定义的时候使用 abstract 关键字标记的一般类。他可包含一般类所包含的所有特性,例如字段,属性,方法,另外还包含一个很特殊的方法,叫抽象方法(这些方法基本上是没有执行代码的函数标题,而派生于该类的类就必须提供执行的代码),而且不能被实例化,主要用在类的定义和部分实现这方面,所以需要在扩充类中完整的扩充并实现功能.

抽象方法: 当类中的方法在声明的时候加上 abstract 关键字的时候,称为abstract method ,但是只有在抽象类和接口中才可以使用抽象方法。

举个例子:

public abstract class person
{
//首先定义一个抽象的人的基类
public int eye;
public int clothes;
public person(int yj, int yf)
{
eye = yj;
clothes = yf;
}
public abstract string GetMore();
//定义一个抽象的方法

}
public class richGril : person
{//富有的女孩继承人的类
public int shoes; //鞋子
public richGril(int yj, int yf, int xz)
: base(yj, yf)
{
eye = yj;
clothes = yf;
shoes = xz;
}
public override string GetMore()
{
return "这是一个富有的女孩,他有" + eye + "漂亮的大眼睛,还有" + clothes + "件漂亮的衣服,和" + shoes + "双鞋子";
}

}
public class poorGril : person
{//贫穷的的女孩继承人的类
public int shoes;//鞋子
public int work;
public poorGril(int yj, int yf, int xz,int gz)
: base(yj, yf)
{
eye = yj;
clothes = yf;
shoes = xz;
work = gz;
}
public override string GetMore()
{
return "这是一个贫穷的女孩,他有" + eye + "漂亮的大眼睛,还有" + clothes + "件漂亮的衣服,和" + shoes + "双鞋子,但是她每天需要干"+work+"份工作";
}
}


接口:他呢其实也是一种特殊的抽象类,用 interface 关键字标记,他的定义没有 class 关键字,他可以包含 方法和属性和事件,但是方法也只能是抽象方法,任何派生于该接口的类就必须提供执行的代码.任何接口成员前面都不能加修饰符.

接口可用的修饰符有 new ,  public  ,protected , internal   ,  private ,但是同一声明中修饰符只能有一个,new关键字只能出现在镶套接口中,表示复写继承来的同名成员.

 

接口和类一样,可以被继承和发展,但不同的是,类继承不仅说明继承也会实现继承,但是接口继承只是说明继承,通俗的说,派生类可以继承基类的方法实现,而派生接口只是继承父接口的方法说明,却没有继承父接口的实现.

这是一个简单的接口例子:

interface firstDemo  //声明第一个接口
{
int Count(int i, int j);  //声明一个属性
}
public class c : firstDemo
{
public int Count(int i, int j)
{
return i + j;
}

}

二、常见问题一盘端

1、接口的继承并不是只继承一个接口,如果是说继承的接口如果还有父接口怎么办?

在这个演示中我们主要说明一个问题,就是如果继承了有父接口的接口,那么也必须实现他全部父接口的方法和属性

interface I_2_A     //声明第一个接口
{
int A { get;set;}   //声明一个属性
}
interface I_2_B     //声明第二个接口
{
int Count(int i,int j); //声明一个方法
}
interface I_2_C : I_2_A, I_2_B { }  //声明第三个接口又继承了前两个接口
//什么都没有声明。但是他实际上是继承了前面两个接口的属性和方法。

public class I_2_L : I_2_C  //声明一个类,他继承了I_2_C这个接口
{
int a;

public int A
{
get { return a; }
set { a = value; }
}
public int Count(int i, int j)
{
return i * j * a;
}
}

2、外部对接口的访问,如果出现同名的参数或者方法,必须显示的指出他的父接口。

public interface I_3_A
{
int Count { get;set;}
int J(int j);
}
public interface I_3_B
{
void Count(int i);
double J(double j);
}
public interface I_3_C : I_3_A, I_3_B { }

public class I_3_L
{
public void Sum(I_3_C thc)
{
thc.Count();  //错误,具有二义性
thc.Count = 1;  //错误,具有二义性
thc.Count(1);   //错误,具有二义性

((I_3_A)thc).Count = 1;     //正确
((I_3_B)thc).Count(1);

((I_3_A)thc).J(1);
((I_3_B)thc).J(1);
thc.J(1.0);
thc.J(1);
}
}


3、外部类中对多重继承中的成员访问问题

public interface I_4_A
{
string F(string A);
}
public interface I_4_B : I_4_A
{
new string F(string A);
}
public interface I_4_C : I_4_A
{
string T();
}

/// <summary>
/// 下面这个接口我们需要注意一下,他继承了B 和 C ,但是这两个有同时继承了 A
/// 不同的是,他们两个接口在内部定义的时候又采取了不同的策略,我们的访问该是如何的呢?
/// </summary>
public interface I_4_D : I_4_B, I_4_C { };

public class I_4_L
{
public string Test(I_4_D thc) //接受的参数类型为接口D类型的
{
thc.T();    //这个好理解,他直接调用 C接口的 T方法
thc.F("B接口的方法");    //这个呢就直接访问的B接口的F方法,虽然A接口也有一个F方法,但是他这里new了,就是说拦截了向上的访问
((I_4_A)thc).F("A接口的方法"); //通过明确指定的方法来访问A接口的F方法
((I_4_C)thc).F("A接口的方法"); //因为在C接口中并没有复写A接口的F方法,所以还是可以直接访问的
((I_4_D)thc).F("B接口的方法"); //同理是访问B接口的F方法,跟我们第二行的直接访问是一个道理
}
}

4、 本例我们说明三个问题,一是显示的实现接口

 被显示实现的接口成员不能被从类实例访问. 因为不能在类实例中访问,但是在类内部是可以的吧,当类的使用者不需要使用到这个接口成员的时候

这个特性就特别有用了

另外如果多个接口之间有同名成员的时候,这个就特别有用了

要显示调用的话就必须继承接口

public interface I_5_A
{
string Name { get;set;}
double Price { get;set;}

string X_More();
string More();
}

public class I_5_L : I_5_A
{
private string name;
private double price;

public I_5_L()
{
name = "123";
price = 888.888;
}

#region I_5_A 成员

string I_5_A.Name   //显示实现的属性,显示声明也没必要用到修饰符
{
get { return name; }
set { name = value; }
}

public double Price
{
get { return price; }
set { price = value; }
}

string I_5_A.X_More()   //显示实现的方法
{
string more = name + price.ToString();
return more;
}

public string More()
{
string more = name + price.ToString();
return more;
}

#endregion
}
5、使用override关键字实现进行复写
public class I_6_L_2 : I_6_L_1,I_6_A
{
string  I_6_A.GetUrl()
{
return "thcjp.thc123.com";
}
string I_6_A.GetName()
{
return "天轰穿的博客";
}
}

/// <summary>
/// 这个类也继承了I_6_L_1 这个类,而且使用override关键字对I_6_L_1 中的方法实现进行复写
/// 所以当调用的时候,结果自然可想而知了
/// </summary>
public class I_6_L_3 : I_6_L_1
{
public override string GetUrl()
{
return "你们好啊";
}
public override string GetName()
{
return "helloworld";
}
}

/// <summary>
/// 这个类很显然古怪出在对方法的实现上,他使用了new关键字
/// 不是复写的问题,更严重了,根本就是把父类的实现给覆盖了
/// </summary>
public class I_6_L_4 : I_6_L_1
{
public new string GetUrl()
{
return "大家好";
}
public new string GetName()
{
return "提高班欢迎您";
}
}


6、映射:

public interface I_7_A
{
string G();
}
public interface I_7_B
{
string G();
}

//这里我们需要注意的是,上面 A 和B  都有一个成员方法

public class I_7_L:I_7_A,I_7_B
{

#region

public string G()
{
return "隐式实现的 : asp.net";
}

#endregion

#region I_7_B 成员

string I_7_B.G()
{
return "显式实现的 : asp.net ,hello";
}

#endregion
}


还有就是我们需要关于虚方法,override 和 new的一些继承问题,因为虚方法和override和new的用法有所不同,一篇博客无法介绍清楚,所以放在单独的一篇博客。
                                                                                      -----原文代码参考天轰穿视频
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息