C#基础教程.docx
《C#基础教程.docx》由会员分享,可在线阅读,更多相关《C#基础教程.docx(57页珍藏版)》请在冰点文库上搜索。
C#基础教程
C#语言
基于Web的应用程序在过去几年非常流行。
从管理员的角度来看,把所有的应用程序逻辑放在一个中央服务器上是非常吸引人的。
但部署基于客户的软件会非常困难。
基于Web的应用程序的缺点是它们不能提供丰富的用户体验。
.NETFramework允许开发人员创建丰富、智能的客户应用程序,而且不再有部署问题。
.NET提供的新部署服务以及组成Windows窗体的System.Windows.Forms和System.Windows.Forms.Design命名空间,将使客户应用程序重新流行起来。
Windows窗体已经对Windows开发产生了影响。
当应用程序处于初始设计阶段时,是建立基于Web的应用程序还是建立客户应用程序已经很难抉择了。
Windows客户应用程序开发起来非常快速和高效,它们可以为用户提供丰富的体验。
第一部分面向对象
(九)方法的抽象和类的抽象
练习
(二)
我们继续,下面的例子展示了抽象的属性,我们说过,一个对象的属性由一组get/set方法来表现,所以属性也可以作为抽象存在。
下面的例子我们定义了Person类,其EyeColor属性为一个抽象属性,由其子类来具体定义。
看代码:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceEdu.Study.OO.UseAbstact2{
///
///又见人类
///
publicabstractclassPerson{
///
///人名字字段
///
privatestringname;
///
///构造器,输入人名
///
publicPerson(stringname){
this.Name=name;
}
///
///人名属性
///
publicstringName{
get{
returnname;
}
set{
name=value;
}
}
///
///定义一个抽象属性,指明这个属性必须具备get/set访问器,都是抽象的
///这里为了明确,所以为该属性定义了set访问器,其实也不是没有道理,戴个隐形眼镜就可以改变眼睛的颜色了
///当然,也可以只定义某一个访问器,形成抽象只读属性或抽象只写属性
///
publicabstractstringEyeColor{
get;
set;
}
}
///
///定义亚洲人类,继承自人类
///
publicclassAsiaPerson:
Person{
///
///隐形眼镜颜色字段
///
privatestringlensesColor;
///
///构造器,调用超类构造器
///
publicAsiaPerson(stringname)
:
base(name){
}
///
///眼睛颜色属性,实现超类抽象属性
///
publicoverridestringEyeColor{
get{
//如果戴隐形眼镜,则返回隐形眼镜的颜色,否则返回黑色
if(this.lensesColor!
=null){
returnthis.lensesColor;
}else{
return"Black";
}
}
set{
//无法设置眼睛的颜色,所以给隐形眼镜加上颜色
this.lensesColor=value;
}
}
}
///
///欧洲人类
///
publicclassEuropePerson:
Person{
///
///隐形眼镜颜色字段
///
privatestringlensesColor;
///
///构造器,调用超类构造器
///
publicEuropePerson(stringname)
:
base(name){
}
///
///眼睛颜色属性,实现超类抽象属性
///
publicoverridestringEyeColor{
get{
//如果戴隐形眼镜,则返回隐形眼镜的颜色,否则返回蓝色
if(this.lensesColor!
=null){
returnthis.lensesColor;
}else{
return"Blue";
}
}
set{
//无法设置眼睛的颜色,所以给隐形眼镜加上颜色
this.lensesColor=value;
}
}
}
classProgram{
staticvoidMain(string[]args){
Personperson=newAsiaPerson("王毛毛");
Console.WriteLine("{0}眼睛颜色为:
{1}",person.Name,person.EyeColor);
person.EyeColor="Brown";
Console.WriteLine("{0}眼睛颜色为:
{1}",person.Name,person.EyeColor);
person=newEuropePerson("WangMaomao");
Console.WriteLine("{0}眼睛颜色为:
{1}",person.Name,person.EyeColor);
person.EyeColor="Green";
Console.WriteLine("{0}眼睛颜色为:
{1}",person.Name,person.EyeColor);
}
}
}
另外,我们也可以单独定义get或set访问器中的一个为抽象。
这里就不做展示了。
C#语言
第一部分面向对象
(九)方法的抽象和类的抽象
练习
(一)
上一章我们讲了方法和类的抽象,这一章我们从一些例子,继续加深对抽象的理解。
第一个例子,我们定义了形状类(Shap类),从类名字就可以看出该类必然是一个抽象类。
形状……本来就很抽象嘛。
好了,既然是形状,就必然有面积,Shap类的Area方法必然是一个抽象方法。
接下来,我们创建一个子类:
正多边形类(Polygon类),继承自Shap类。
这个类比形状类具体多了,我们知道了一个新的属性:
边长。
但只知道边长依旧无法求出形状的面积,所以其继承下来的Area方法依旧只能作为抽象方法,所以Polygon类仍是一个抽象类。
最后,定义正四边形类和正五边形类,这两个类显然非常具体了,可以定义Area方法了。
就这样,看代码:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceEdu.Study.OO.UseAbstract{
///
///定义形状类
///
publicabstractclassShap{
///
///定义抽象方法,求面积,对于形状类,面积方法没有方法体
///
///面积
publicabstractdoubleArea();
}
///
///定义多边形类,此类继承了Area方法,但并未实现,所以依旧是抽象类
///
publicabstractclassPolygon:
Shap{
///
///边长字段
///
privatedoublesideLength;
///
///构造器,输入边长
///
publicPolygon(doublesideLength){
this.SideLength=sideLength;
}
///
///边长属性
///
publicdoubleSideLength{
get{
returnsideLength;
}
set{
if(value>0){
sideLength=value;
}else{
Console.WriteLine("边长必须大于0。
");
}
}
}
}
///
///定义正方形类,继承自多边形类(Polygon类)
///
publicclassSquare:
Polygon{
///
///构造器
///
publicSquare(doublesideLength)
:
base(sideLength){
}
///
///求正方形面积,实现超类的抽象方法
///
publicoverridedoubleArea(){
returnMath.Pow(this.SideLength,2);
}
}
///
///定义五边形类
///
publicclassPentagon:
Polygon{
///
///构造器
///
publicPentagon(doublesideLength)
:
base(sideLength){
}
///
///求五边形面积,这里使用工程计算求近似值,即边长的平方乘以系数1.72
///
publicoverridedoubleArea(){
returnMath.Pow(this.SideLength,2)*1.72F;
}
}
classProgram{
staticvoidMain(string[]args){
//使用Shap类变量引用到Square类实例上
Shapshap=newSquare(10);
//输出面积结果
Console.WriteLine("面积={0}",shap.Area());
//使用Shap类变量引用到Pentagon类实例上
shap=newPentagon(10);
//输出面积结果
Console.WriteLine("面积={0}",shap.Area());
}
}
}
C#语言
第一部分面向对象
(八)方法的抽象和类的抽象
Technorati标签:
C#,学习
当我们对客观事物进行分类时,常常会遇到这样一个问题:
有一些类并不知道自己的某些方法具体的实施流程是什么。
这样的类非常多,例如有一个Person类,其必然有一个Speak方法,因为所有的Person都可以Speak,但当我们设计Person类时,却无法写出Speak方法体内的一行代码。
因为Person类太概括了,如果不明确的指出是哪一国人,我们无法得知Speak方法具体怎么发生。
一个类,具有某个行为,但无法得知该行为的具体流程。
这样的行为称为抽象行为,体现在代码中就是“抽象方法”。
好了,现在我们有一个拥有抽象方法的类,那当我们试图生成这个类的实例时,矛盾就产生了。
实例一旦生成,就表明它是一个客观存在的具体事物,不可能存在尚未确定的方法。
所以一旦一个类中具备抽象的方法,则这个类被称为“抽象类”。
抽象类无法实例化对象,这是规定。
抽象是面向对象语言的类得以连续继承的关键。
OK,总结一下:
超类定义了两部分方法,
?
一部分方法,超类知道其执行流程,这部分方法要么被子类直接继承,要么被子类继承后覆盖;
?
一部分方法,超类并不知道其具体执行流程,所以超类给出定义,由知道其具体执行流程的那个子类来覆盖实现该方法。
好了,我们来举个例子:
usingSystem;
namespaceEdu.Study.OO.Abstract{
///
///依旧创建一个人类,这次这个类是“抽象”的,abstract关键字表示抽象
///
publicabstractclassPerson{
///
///名称字段
///
privatestringname;
///
///年龄字段
///
privateintage;
///
///性别字段
///
privateboolsex;
///
///构造器
///
publicPerson(stringname,intage,boolsex){
this.Name=name;
this.Age=age;
this.sex=sex;
}
///
///性别属性(只读)
///
publicboolSex{
get{
returnsex;
}
}
///
///年龄属性
///
publicintAge{
get{
returnage;
}
set{
age=value;
}
}
///
///姓名属性
///
publicstringName{
get{
returnname;
}
set{
name=value;
}
}
///
///去厕所的方法(抽象),abstract关键字表示方法抽象
///
publicabstractvoidGoToilet();
}
///
///男人类,继承自Person类
///
publicclassMan:
Person{
///
///构造器
///
publicMan(stringname,intage)
:
base(name,age,true){
}
///
///抽烟方法
///
publicvoidSmork(){
Console.WriteLine("{0}抽了一支烟。
",this.Name);
}
///
///去厕所的方法(实现超类抽象方法,注意要使用override关键字)
///
publicoverridevoidGoToilet(){
Console.WriteLine("{0}解决了燃眉之急。
",this.Name);
this.Smork();
}
}
///
///女人类,继承自Person类
///
publicclassWoman:
Person{
///
///构造器
///
publicWoman(stringname,intage)
:
base(name,age,false){
}
///
///女人化妆的方法
///
publicvoidMakeup(){
Console.WriteLine("{0}化妆完毕。
",this.Name);
}
///
///女人去厕所方法(实现超类抽象方法,注意要使用override关键字)
///
publicoverridevoidGoToilet(){
Console.WriteLine("{0}解决了燃眉之急。
",this.Name);
this.Makeup();
}
}
///
///厕所类
///
publicclassTolite{
///
///进入厕所的方法
///
publicvoidComming(Personperson){
person.GoToilet();
}
}
classProgram{
staticvoidMain(string[]args){
//一旦成为抽象类,则无法实例化对象
//Personperson=newPerson("小张",22,true);
//定义一男一女
Manzhang=newMan("小张",22);
Womanli=newWoman("小丽",18);
//定义厕所对象
Tolitetolite=newTolite();
//一男一女去厕所
tolite.Comming(zhang);
tolite.Comming(li);
}
}
}
可以看到,子类一旦继承了一个抽象类,就应该实现超类中的抽象方法,使子类得以能够创建实例。
但如果子类确定无法实现超类中定义的抽象方法,则子类也必须作为一个抽象类存在,因为子类继承了一个抽象方法,但却没有能够覆盖它,给其提供方法体。
一般而言,抽象类中必然存在抽象的方法。
但对于一个没有抽象方法的类,也可以使用abstract关键字声明其为抽象类,此时这种声明方法仅仅是为了阻止这个类实例化,指明这个类必须被继承而已。
C#语言
第一部分面向对象
(七)方法重载
一只狼狗无忧无虑的走在大街上,狼狗天性好斗,所以应该有一个Fight方法。
这时候他碰到了一只小狗,即Puppy类的一个对象,此时狼狗调用Fight方法,将这只puppy作为参数传入,将其狠狠修理了一顿。
不一会儿,它又碰到一只大狗,很凶恶的样子,此时狼狗的心里没有必胜的把握,但它依旧调用了Fight方法,将大狗作为参数传入。
不过这次,Fight方法只是示威了一下而已,叫了几声,然后就结束了。
又过了一会儿,它碰到了一大群狗,即一个狗数组,此时狼狗吓得屁滚尿流,但还是调用了Fight方法,将狗数组作为参数传入。
这次,Fight方法执行的结果,狼狗逃之夭夭了。
可见,在我们现实生活中,总是存在这样一种情况:
某类对象的某种行为,因为外界条件不同(参数不同),执行的具体流程也不同。
体现在编程代码中,就是方法的重载。
在同一个类(或某个类和它的子类)中,一系列同名的方法就构成了“重载”,重载的条件是:
方法名相同,参数列表不同。
对于子类要重载超类方法的情况,超类该方法必须为protected或public类型。
看代码:
usingSystem;
namespaceEdu.Study.OO.Overload{
///
///继续人类
///
publicclassPerson{
///
///保存名字的字段
///
protectedstringname;
///
///保存年龄的字段
///
protectedintage;
///
///保存性别的字段
///
protectedboolsex;
///
///带有参数的构造器
///
publicPerson(stringname,intage,boolsex){
this.Name=name;
this.Age=age;
this.sex=sex;
}
///
///姓名属性
///
publicstringName{
get{
returnthis.name;
}
set{
this.name=value;
}
}
///
///年龄属性
///
publicintAge{
get{
returnage;
}
set{
age=value;
}
}
///
///性别属性
///
publicboolSex{
get{
returnsex;
}
set{
sex=value;
}
}
///
///显示个人信息的方法
///
publicvoidS