C#中抽象类和接口

时间:2023-01-07 17:54:48

   下面是我做的测试:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace ClassDemo
{
class Program
{
static void Main(string[] args)
{
//BaseClass bc = new BaseClass();
//bc.sayHello();

//DerivedClass dc = new DerivedClass();
//dc.sayHello();

//BaseClass bc2 = new DerivedClass();
//bc2.sayHello();

//Test test = new Test();
//test.sayHello();

//BaseClass bc = new DerivedClass2();
//bc.sayHello();

//索引器
//IndexDemo id = new IndexDemo();
//id[0] = "chen";
//id[1] = "yu";
//id[2] = "ming";
//Console.WriteLine("{0}{1}{2}", id[0], id[1], id[2]);

//抽象类和接口
//ITest it = new ITest(); //error:无法创建抽象类或接口的实例
//ATest at = new ATest(); //error:无法创建抽象类或接口的实例
Test t = new Test();
t.sayHello();
//t.X = 100;
//Console.WriteLine(t.X);
Test2 t2 = new Test2();
t2.sayHello();
Console.WriteLine(t2.add());
Console.WriteLine(t2.add2());
t2.x
= 10;
Console.WriteLine(t2.x);
}

//嵌套类
private class Test //类里面定义类,这里的类是可以有修饰符的private
{
public void sayHello()
{
Console.WriteLine(
"ClassTest sayHello");
}
}
}

//抽象类与接口
public interface ITest
{
//public int x; //error:接口不能包含字段
void sayHello(); //error:不能有如public、abstract的修饰符
//int add() { return 1 + 2; }//error:接口成员不能有定义
int X { get; set; }
}

public class Test : ITest
{
private int _x;
public void sayHello()
{
Console.WriteLine(
"Test sayHello");
}
public int X { get { return _x; } set { _x = value; } }
}

abstract class ATest
{
public int x;
public abstract void sayHello();
public int add() { return 1 + 2; }
public virtual int add2() { return 2 + 3; }
}

class Test2 : ATest
{
public override void sayHello()//重写virtual、abstract必须通过override
{
Console.WriteLine(
"Test2 sayHello");
}

public override int add2() { return 3 + 4; }
}

public class BaseClass //命名空间中定义的元素无法显式声明为private、protected 或protected internal但可以是public
{
public BaseClass()
{
Console.WriteLine(
"BaseClass");
}
public BaseClass(string str)
{
Console.WriteLine(
"BaseClass " + str);
}
public virtual void sayHello()
{
Console.WriteLine(
"BaseClass sayHello");
}
}

class DerivedClass : BaseClass
{
public DerivedClass()
{
Console.WriteLine(
"DerivedClass");
}

public new void sayHello()//有意掩藏基类的方法 new
{
Console.WriteLine(
"DerivedClass sayHello");
}

public void drawLine(params Point[] pt)
{

}
}

class Point
{
private int _x;
public int X { get { return _x; } set { _x = value;} }
private int _y;
public int Y { get { return _y; } set { _y = value; } }
}

//void sayHello()//error:命名空间并不直接包含诸如字段或方法之类的成员
//{
//}

class DerivedClass2 : BaseClass
{
public override void sayHello()
{
Console.WriteLine(
"DerivedClass2 sayHello");
}
}

class IndexDemo
{
protected ArrayList al = new ArrayList();

public object this[int index]
{
get
{
if (index > -1 && index < al.Count)
{
return al[index];
}
else
{
return null;
}
}
set
{
if (index > -1 && index < al.Count)
{
al[index]
= value;
}
else if (index == al.Count)
{
al.Add(value);
}
else
{

}
}
}
}
}

  以上测试得出以下几个结论:

  1、抽象类与接口均不能实例化。

  2、接口不能包含字段。

  3、包含的方法只能有声明,不能定义,且不能有如public、abstract的修饰符。

  4、抽象类与一般的类的的区别是:它不能实例化。

  

  一、抽象类:
      抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们。

      二、接口:
      接口是引用类型的,类似于类,和抽象类的相似之处有三点:
      1. 不能实例化;
      2. 包含未实现的方法声明;
      3. 派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);
      另外,接口有如下特性:
      接口除了可以包含方法之外,还可以包含属性、索引器、事件,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类可以直接继承多个接口,但只能直接继承一个类(包括抽象类)。

      三、抽象类和接口的区别:
      1. 类是对对象的抽象,可以把抽象类理解为把类当作对象,抽象成的类叫做抽象类.而接口只是一个行为的规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做。。。”。抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中;
      2. 接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;
      3. 一个类一次可以实现若干个接口,但是只能扩展一个父类;
      4. 接口可以用于支持回调,而继承并不具备这个特点;
      5. 抽象类不能被密封;
      6. 抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的;
      7.(接口)与非抽象类类似,抽象类也必须为在该类的基类列表中列出的接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上;
      8. 抽象类实现了oop中的一个原则,把可变的与不可变的分离。抽象类和接口就是定义为不可变的,而把可变的座位子类去实现;
      9. 好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染;
     10. 尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中某一类,就必须把他们全部加载到栈中!后果可想而知。(结合堆栈原理理解)。同时,有心的朋友可以留意到微软在构建一个类时,很多时候用到了对象组合的方法。比如 asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是非常基本的一个设计原则;
     11.如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法。 

      四、抽象类和接口的使用:
      1. 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本;
      2.如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口;
      3.如果要设计大的功能单元,则使用抽象类。如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类; 
      4.抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。