—————————————————————————————————————————————
抽象类
把实例化没有意义的父类,改成抽象类。把类和方法声明为abstract,也就是抽象类和抽象方法。
注意:抽象类不能实例化;抽象方法是必须被子类重写的方法;如果类中包含抽象方法,那么类就必须定义为抽象类,无论是否包含其他一般方法。
考虑抽象类拥有尽可能多的共同代码,拥有尽可能受的数据。
抽象类通常代表一个抽象概念,它提供一个继承的出发点,当设计一个新的抽象类时,一定是用来继承的,所以,在一个以继承关系形成的等级结构里面,树叶节点应当是具体类,而树枝节点均应当是抽象类。
//加abstract关键字,表明是抽象类
abstract class Animal
{
//在方法返回值前面加abstract,表明此方法是抽象方法,抽象方法没有方法体,直接在括号后面加“;”
protected abstract string getShoutSound();
}
接口
接口是把隐式公共方法和属性组合起来,以封装特定功能的一个集合,一旦类实现了接口,类就可以支持接口所指定的所有属性和成员,声明接口在语法上与声明抽象类完成相同,但不允许提供接口中任何成员的执行方式,所以接口不可以实例化,不能有构造方法和字段,不能有修饰符,不能声明虚拟的或静态的,还有实现接口的类必须要实现接口中的所有方法和属性。
一个类可以支持多个接口,多个类也可以支持相同的接口。接口的命名,前面要加一个大写的字母“I”,接口用interface声明,接口中的方法或者属性前面不能有修饰符、方法没有方法体。
interface IChange
{
string ChangThing(string thing);//声明一个IChange接口,此接口有一个方法ChangThing,参数是一个字符串变量,返回一个字符串。
}
class MachineCat:Cat,IChange//机器猫继承于猫,并实现IChange接口
{
public MahcineCat():base()
{}
//实现接口的方法,注意不能加override修饰符
public string ChangThing(stirng thing)
{
//base.Shout()表示调用父类cat的方法
return base.Shout ()+"我有万能口袋,我可以变出:"+thing;
}
}
客户端代码
private void button_Click(object sender,EventArgs e)
{
MachineCat mcat=new MacineCat("叮当");//创建两个类的实例
StoneMonkey wukong =new StoneMonkey("孙悟空");
IChange[]array=new IChange[2];//声明一个接口数组,将两个类实例赋值给数组
array[0]=mcat;
array[1]=wukong;
//利用多态性,实现不同的changething
MessageBox.Show(array[0].ChangeThing("各种各样的东西"));
MessgaeBox.Show(array[1].ChangeThing("各种各样的东西"));
}
抽象类和接口的区别:
抽象类可以给出一些成员的实现,接口却不包含成员的实现,抽象类的抽象成员可被子类部分实现,接口的成员需要实现类完全实现,一个类只能继承一个抽象类,但可实现多个接口等等。
类是对对象的抽象,抽象类是对类的抽象,接口是对行为的抽象;如果行为跨越不同类的对象,可以使用接口,对于一些相似的类对象,用继承抽象类;从设计角度讲,抽象类是从子类中发现了公共的东西,泛化出父类,然后子类继承父类,而接口是根本就不知道子类的存在,方法如何实现还不确认,预先定义。
(抽象类是自底而上抽象出来的,而接口是自顶向下设计出来的)
集合
数组的优点:数组在内存中连续存储,因此可以快速而容易的从头到尾便利元素,可以快速修改元素等。
缺点:创建时必须要指定数组变量的大小,还有在两个元素之间添加元素也比较困难。
集合和数组
ArrayList是命名空间,System.Collections的下一部分,它是使用大小可按需动态增加的数组实现IList接口。
ArrayList的容量是ArrayList可以保存的元素数,ArrayList的默认初始容量为0。随着元素添加到ArrayList中。容量会根据需要通过重新分配自动添加。使用整数索引可以访问此集合中的元素。此集合中的索引从零开始。
using System.Collections;//增加此命名空间
public partial class Form1:Form
{
IList arrayAnimal;//声明一个集合变量,可以用接口IList,也可以直接声明“ArrayList arrayAnimal”
//动物报名按钮事件
private void button_Click(object sender,EventArgs e)
{
arrayAnimal=new ArrayList();//实例化ArrayList对象,注意这里并没有指定arrayAnimal的大小,与数组不相同
//调用集合的add方法增加对象,其参数是object,所以new cat和new dog都没有问题。
arrayAnimal.Add(new Cat("小花"));
arrayAnimal.Add(new Cat(""));
arrayAnimal.Add(new Cat(""));
arrayAnimal.Add(new Cat(""));
arrayAnimal.Add(new Cat(""));
MessageBox.Show(arrayAnimal.Count.ToString());//随着add对象的增加,集合的Count可以得到当前的元素个数。
}
}
arrayAnimal.RemoveAt(1);//移除指定索引处的集合项。
装箱和拆箱
装箱就是把值类型打包到object引用类型的一个实例中。拆箱就是指从对象中提取值类型。
装箱和拆箱过程需要进行大量的计算,对值类型进行装箱时,必须分配并 构造一个全新的对象。其次,拆箱所需要的强制转换也需要进行大量的计算。
泛型
泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段和其方法的参数类型出现。
using System.Collections.Generic;//增加泛型集合的命名空间
public partical class Form:Form
{
IList<Animal>arrayAnimal;//关键在这里,声明一个泛型集合变量,用接口IList,注意IList<Animal>表示此集合变量只能接受Animal类型,其他不可以,也可以直接声明List<Animal>arrayAnimal;
//动物报名按钮事件
private void button_Click(object sender,EventArgs e)
{
arrayAnimal=new List<Animal>();//实例化list对象,注意,此时也需要指定list<I>的I是Animal
arrayAnimal.Add(new Cat("小花"));
arrayAnimal.Add(new Cat("小花"));
arrayAnimal.Add(new Cat("小花"));
arrayAnimal.Add(new Cat("小花"));
arrayAnimal.Add(new Cat("小花"));
MessageBox.Show(arrayAnimal.Count.ToString());
}
}
List 和ArrayList在功能上一样的,不同在于,它在声明和实例化时都需要指定其内部项的数据或对象类型。
通常情况下,都建议使用泛型集合,因为这样可以获得类型安全的直接优点,而不需要从基集合类型派生并实现类型特性的成员,此外,如果集合元素为值类型,泛型集合类型的性能通常优于对应的非泛型集合类型(并优于从非泛型基集合类型派生的类型),因为使用泛型时不必对元素进行装箱。
委托和事件
委托是对函数的封装,可以当做给方法的特征指定一个名称,而事件则是委托的一种特殊形式,当发生有意义的事情时,事件对象处理通知过程。
委托是一种应用方法的类型,一旦为委托分配了方法,委托将与该方法具有完全相同的行为,委托对象用关键字delegate来声明,而事件是说在发生其他类或对象关注的事情时,类或对象可通过事件通知他们,事件对象用event来声明。
public delegate void CatShoutEventHandler();
//声明一个委托,委托的名字叫做CatShoutEventHandler。
public event CatShoutEventHandler CatShout;
//声明一个事件CatShout,它的事件类型是委托CatShoutEventHandler