纵观MicroSoft公司的几种主流语言,C是面向过程,VB既有面向过程也有面向对象的特性,而C#则是纯粹的面向对象的编程语言。在UML的学习过程中,画类图、对象图的时候面向对象的思想就已经用到了具体的学习中,而C#的学习过程中我们接着深入来学习这种思想,只不过这次是把OOP的思想用到了实际的代码编程之中。
我们知道面向对象的四个基本原则:抽象、封装、模块化、层次性;面向对象思想的编程特性:继承性、封装性、多态性。通过楚老师的视频,对面向对象的四个基本原则和编程特性都有了新的认识,这篇博客就先对其中的部分特性进行分析。
在上一篇博客中,对C#基础的分析是以“数据”引出来的,数据中变量在程序设计中占有一席之地,那我们就从静态变量和非静态变量两个角度对它进行分析。
using system; using system.Collections.Generic; using System.text namespace ConsoleApplication1 { class TestStatic { public static void main() { int k=AccessTest.x; //此处直接使用,如果不是静态变量则写成 AccessTest myOk = newAccessTest(); Console.WriteLine(k); AccessTest myOk=new AccessTest(); Cosole.WriteLine(myOK.y); //通过实例化才能访问y } } public class AccessTest { public static int x=12; public int y=12; } }
由例子可知,在AccessTest类中定义了两个变量x和y,其中x为静态static,y为非静态,在TestStatic类的Main函数如果要分别对AccessTest类中的x和y进行访问,则对于x可以直接使用,而对于y需要首先实例化AccessTest类,然后再由该实例去调用其中的y。也就是说静态变量中的成员可以通过类名直接进行访问,而实例成员(非静态变量)必须通过建立对象的引用来访问(此处区别对象和对象引用,对象引用是一个地址而不是一个值)。我想如果x和y都定义成了非静态变量的话,那样代码量会大增的。
通过学习,对static变量有了自己的认识,但是理解的程度仅限于此,至于在代码中何处该用静态变量,还有待于在以后的学习中去探索。
所谓的方法,就是对象的行为,在之前学习VB的时候对象有属性、事件和方法,而在真正面向对象的语言中没有事件的概念,或者说事件就是属于方法中的。
方法的句法如下:
[访问修饰符] 返回值类型 <方法名> ([参数列表])//不需要返回值时用void
{
//方法主体
}
正如上面介绍的静态变量和非静态变量那样,调用静态的方法同样无需进行实例化,而非静态的方法需要进行类的实例化之后进行调用该方法。
方法可以被重复调用即“方法重载”在C#中是一个非常重要的定义,视频中老师将其分为“具有不同数量参数的方法重载”和“对不同数据执行相似功能的方法重载”,如下:
Using System; Namespace chognzai { Class Class1 { Public int a,b; Public double x,y; Public int fun(int a,int b) //方法名称相同,参数不同 { Return a+b; } Public double fun(double x,double y) //方法名称相同,参数不同 { Return a+b; } Static void Main(string[] args) { Class1 sd=new Class1(); Sd.a=156; Sd.b=32; Sd.x=23.56; Sd.y=56.49; Console.WriteLine(“{0}+{1}={2}”,sd.a,sd.b,sd.fun(sd.a,sd.b)); Console.writeLine(“{0}+{1}={2}”,sd.x,sd.y,sd.fun(sd.x,sd.y)); Console.ReadLine(); } } }
该例子中成员函数fun()被重载,属于“对不同数据执行相似功能的方法重载”,再次验证了方法是可以多次使用的这个观点。
先看个小例子,这是在视频中非常经典的那个交电话费的例子。
namespace Customer { public enum TypeofCall { callToMobile,CallTOLandLine } class Program { static void Main(string[] args) { Customer tom=new Customer(); tom.CustomerName="楚广明"; //设置属性的值 tom.RecordCall(TypeofCall.callToMobile,20); tom.RecordCall(TypeofCall.callToLandline,40); Console.WriteLine("{0}有{1}电话费要交",tom.CustomerName,tom.customerBalance) //读取属性的值 } } public class Customer { private string name; private decimal balance; public string CustomerName //*****属性****// { get( return name;) set ( name=value;) } public decimal CustomerBalance //****属性***// { get ( return balance;) //只能读取余额,而不能修改 } public void RecordPayment(decimal amountpaid) //***方法*** // { balance-=amountpaid; } public void RecordCall(TypeofCall callType,uint nMinute) //***方法*** // { swistch(callType) { case TypeofCall.CallToLandline: balance+=(0.02M*nMinutes); break; case TypeofCall.callToMobile: balance+=(0.3M*nMinutes); default: break; } } } }
例子有点长,其中仅仅对属性进行分析,就像:
public string CustomerName //*****属性****//
{
get( return name;)
set ( name=value;)
}
public decimal CustomerBalance //****属性***//
{
get ( return balance;) //只能读取余额,而不能修改
}
这两个属性是这个例子中的Customer类实例化后tom对象的两个属性,很明显属性区别于方法就像当初学习VB一样,一个说明的是属性,另一个说的是动作。从这个例子中还能体现出面向对象封装性的思想,就像CustomerBalance属性那样,仅仅为读取属性,而没有设置属性的代码,这样我们在主程序中就不能去修改,从而保护了隐私。也就是说通过属性,将类的成员变量隔离,通过赋值、取值实现间隐藏封装的功能,这也可以看做是一种权限的限制。
通过这个小例子,OOP的封装性也就是通过其他间接的手段去操作类的成员变量,不要让别人知道你的成员变量中包含着什么,当然这里所谓的间接手段可以是上面所提到的属性,也可以是方法,前提是该方法的访问修饰符是public,通过该方法调用相同类中访问修饰符为private的成员变量或者成员方法,从而实现封装,在C#视频中有个“访问密码的最短长度(private)”的例子就是通过这个方法实现的。
在C#中面向对象的思想吗,目前仅仅是了解,需要急切去做的就是到《设计模式》的时候多去敲例子,多去回顾现在学的这些东西,带着问题去学新知识,从而实现“温故而知新”的效果。
在接下来的面向对象总结中将对“继承、多态”做浅析,期待。