类的设计
在介绍类的设计之前先介绍一下关于OOP(Object Oriented Program)中异常处理的情况;
异常处理
在C语言中如果我们碰到了异常情况,常常的做法是返回一个异常数据,我们以去shopping为例结构如下:
int Shoping(int price)
{
if(money < price)
{
return 0;
}
}
在少量的程序中,我们这样写可能不会感到程序的复杂性,如果程序过于庞大,面对成千上万的错误返回根本就没法确定那里出了问题,所以在OOP中引入了异常机制;简单的将就是如果你这里出了问题,将问题类型向上汇报,上级选择性的接收到汇报类型后,执行相关操作。具体的代码结构是
try...catch...finally...
下面我们用一个简单的除0异常来演示;
class Program : Exception
{
static double devide(int a,int b)
{
if (b == 0)
{
Program ex = new Program();
throw ex;
Console.WriteLine("PrintMe");//vs中会有下划线,会提醒没有意义
}
else
{
return a / b;
}
}
static void Main(string[] args)
{
double a;
try
{
a=devide(3, 0);
Console.WriteLine(a);
}
catch (Program e)
{
Console.WriteLine(“test”);
}
finally
{
Console.WriteLine("This is test end");
}
Console.ReadKey();
}
}
这里的类Program继承(下节讲解)于Expection类,程序从Main()函数执行,当执行divide时抛出异常(throw关键字,抛出的类需要是或继承于Expection类),抛出后然后程序依次向后寻找捕获地点即catch(),当该异常被捕获执行捕获中的程序,这个程序里面为
Console.WriteLine(e.ToString());
Catch后面可以不接任何类型,表示无条件接受各种异常,这样对异常的跟踪不利。可以把catch后面的括号及其内容去掉,程序任然是可以运行的。
finally的用法是不管程序有没有异常都要执行finally中的语句,这个在文件读取中很有用,我们在读取文件并且执行操作后,不管我们有没有操作成功都要释放资源。
在C#中已经给定了很多现成的expection类,有些我们只需要直接调用就行了,具体的就看实践了。不能多说没有用C#做个大项目这里面水很深。
类的访问权限
在OOP中,类中方法和属性的权限有三种
public
protected
private
其中public 顾名思义就是大家都可以看,private就是只有自己的类可以看,protected受保护的就是自己和“儿女”(继承)可以看。如果前面不加任何关键字默认是private的。
我们用方法来说明
class Test
{
public void show1()
{
Console.WriteLine("show1");
}
protected void show2()
{
Console.WriteLine("show2");
}
private void show3()
{
Console.WriteLine("show3");
}
}
class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.show1();
test.show2();
test.show3();
}
}
VS会友好的提醒你show2()和show3()是不能够运行的,无法通过编译,只有show1()才能够通过Program类中访问;好奇的同学可以通过在Test类中写个方法自己调用这三个方法,不用质疑自己的东西,自己肯定能用。
为什么要这样设计,这样设计的好处就是可以很好的隐藏细节。我们在编程的时候可以很专注的去了解我们需要的东西,而不需要关心内部的实现方法。就好像你让你的员工干活,不管你怎么干,我只要你给我结果就好了。还有就是有了类的封装可以避免很多误操作,在C语言中如果有上万行的程序,到最后怎么命名都是一个麻烦事,因为要保证所有的函数不重名。
构造函数
构造函数就是我们构造对象的时候要执行的函数,就是初始化函数内部的参数,就好比你要约女孩子(具体对象),你的让女孩子化妆一下吧,在程序员的世界里,化妆的步骤可以自己设定,粉底口红什么的,顺序完全按照自己的意思来,只要自己能够接受,当然不化妆也是可以的上面几个例子就是典型,其实这些也是执行了构造函数的,只是函数里面什么也没有罢了。
构造函数基本结构
class Program
{
public Progarm()
{}
}
我们好奇的同学可以将public改为private试试,你会发现没法创建了。这个就是典型的孤僻症,活在自己的世界了,没有对外的接口,别人没法创建你,活该孤独一辈子。当然设为private也不是没有办法创建,不让别人创建可以自己创建,然后抛出去就行了。
class Program
{
private Progarm()
{}
public static Program CreatProgram()
{
return new Progam()
}
}
为什么要用static,参考上节...
构造函数也可以加参数,可以有多个,不同的参数对应不同的构造函数,给女孩子的化妆方案也要准备好几套不是么?不同化妆品对应的化妆方法是可以相同也可以不同的吧!
class Test
{
private string name;
public Test()//自己写方法
{
name = "defalut name";
}
public Test(string name)
{
this.name = name;
}
public void show1()
{
Console.WriteLine("show1"+name);
}
}
class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.show1();
}
}
我们经常把一些重要的执行方法,现在你可以去看看,在VS中新建一个默认的图像化窗口中,在构造函数中有一个InitComponent()函数,这个函数的作用是绘制整个图形界面!具体是怎么的下下节再提及。
析构函数
析构函数在C#中作用不是特别大,在C++中主要作为对象回收用,由于有.net平台自动回收机制,可以不写,具体作用就是约会完了,你的送她回家吧。在C#中你有专门的司机送她回,不用你管,C++得自己送。
属性
C#中引入了属性这一概念,这是在C++和java中没有的,属性其实就是针对自身变量读取的一个限制。OOP中鼓励奖变量设为私有,然后通过方法获取数据。下面加红部分就是属性的定义,主要Name后面没有括号,如果没有get表示为只写,没有set 表示只读.里面也可以自己写些限制,比如name不能是”tom“之类的,不满足时要以异常的形式抛出去。自己可以下去试试!
class Test
{
private string name;
public string Name
{
get{
return name;
}
set{
name = value;
}
}
public Test()
{
name = "defalut name";
}
public Test(string name)
{
this.name = name;
}
public void show1()
{
Console.WriteLine("show1 "+name);
}
protected void show2()
{
Console.WriteLine("show2"+name);
}
private void show3()
{
Console.WriteLine("show3"+Name);
}
}
class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.Name = "jake";
test.show1();
Console.ReadKey();
}
}
个人感觉,属性的用法和公共变量用法很相似,只是添加了对数据的限制,至于微软为什么要这样设计就不明白了,如果有大牛看到希望指点迷津。
下一节:继承,多态,接口
To be continue...