95992828九五至尊2

目标的卷入与C882828九五至尊手机版

二月 4th, 2019  |  882828九五至尊手机版

《叩开C#之门》种类之三

《叩开C#之门》体系之五

三、对象的包装与C#的类

五、const、readonly和static

面向对象思想有多个为主元素:封装、继承与多态。如能正确精通那三要素,那么基本上可以算是在编程中确立了面向对象思想。在第三节中本人曾介绍,在C#中,所有数据类型的实例都是“对象”,不过最能显示对象特质的品类,照旧“类”,同时它也是C#中最根本、最频仍使用的品种。接下来,我将透过介绍C#的类,来丰盛知情对象封装的概念。

在第三节中,我介绍了常量的定义,其根本字就是const。在概念常量时,必须予以其早先值。一旦赋予了初阶值后,就不能够修改其值。也就是所谓的常量值无法更改的意义。由于C#是一门纯粹的面向对象语言,并不存在一个常量或者变量游离于对象之外,由此,这几个概念,必然都是在一个体系内成功的。

所谓“对象”,形象地说,大家得以把它知道为一块积木。设计积木的人须求规划积木的外观与形态,还有中间的材料。堆积木的人对于里边的材质并不关怀,他们只须求基于分裂的外观与形制来支配堆放的职位。由此,对于开发者而言,要统筹面向对象的次第,同时会是八个截然差异不一致的身价:设计者与使用者。

关于常量的运用,除了会用作一些算法的临时常量值以外,最器重的是概念一些大局的常量,被其他对象直接调用。而集中那几个常量最好的门类是struct(结构)。关于struct我会在后头的章节详细讲解,在此地仅举一例表明常量的那种使用。例如,大家要求在.Net下使用FTP,那么有些一定的FTP代码就足以经过那种方法成功定义,如下所示:
public struct FtpCode
{
 public const string ConnectOk = “220”;
 public const string RequiredPassword = “331”;
 public const string LoginOk = “230”;
 public const string PasvOk = “227”;
 public const string CwdOk = “250”;
 public const string PwdOk = “257”;
 public const string TransferOk = “226”;
 public const string ListOk = “150”;
 public const string PortOK = “200”;
 public const string NoFile = “550”;
}

先谈谈使用者。使用者的身份,就是使用已经提需求您的享有目标,根据需要,设计出自己索要贯彻的主次。就像堆积木的历程。那恰恰是面向对象编程的优势所在,这就是“对象的重用”。已经规划好的靶子,可以被分化的使用者调用,那一个功用既然已经落到实处,对于使用者而言,当然就免去了协调去规划的历程。正如堆积木那样,既然有了现成设计好的积木,使用者所要做的工作就是把那一个积木末了结合起来,堆成差其他模样。.Net
Framework所提供的类库,就是那般的积木。

要利用那么些常量,可以直接调用,例如FtpCode.ConnectOk。如若社团FtpCode仅用于本程序集内部,也得以把结构类型和里面的常量设置为internal。选择那种方法有多个便宜:
1、集中管理全局常量,便于调用;
2、便于修改,一旦Ftp的特定代码暴发变化,仅须求修改FtpCode中的常量值即可,其他代码均不受影响;
3、便于增添。要加进新的Ftp代码,可以一向改动结构FtpCode,其他代码不受影响。

诸如大家想把一个int类型转换成字符型,就从未有过需求自己去落到实处那种转移,直接调用.Net
Framework提供的法力就可以了:
int i = 10;
string s = i.ToString();

固然说变量的值可以修改,但大家也足以定义只读的变量,方法就是在概念的时候增长关键字readonly。如下概念:
public readonly int number = 20;

再例如大家想弹出一个Windows音讯框,同样可以向来使用.Net
Framework现有的类库:
MessageBox.Show(“Message”);

变量number的值此时是只读的,无法再对其进行再次赋值的操作。在概念只读变量的时候,提议必须为变量赋予初值。借使不予以初值,.Net会给予警告,同时根据其品种分化,赋予区其余初值。例如int类型赋初值为0,string类型赋初值为null。由于定义的只读变量其值不得修改,由此不赋初值的只读变量定义,没有其余意义,反而不难造成空引用对象的百般。

在上述的例子中,i和MessageBox都是一个对象。

static的意义与const和readonly迥然不相同。const仅用于常量定义,readonly仅用于变量定义,而static则和常量、变量非亲非故,它是指所定义的值与品种有关,而与对象的事态非亲非故。

再商量设计者的地位。即便.Net
Framework的类库作用已经尤其有力,但它不容许考虑到工作的一切,若是急需利用一个一直就不设有的靶子,此时就须求自己来安顿了。例如图书管理连串,可能就要求用户,图书等对象。那就必要开发者自己来陈设那么些目的。

眼前我已介绍,所谓“对象”,能够叫做一个门类的实例,以class类型为例,当定义了一个类类型之后,要开创该类型的对象,必须进行实例化,方可以调用其质量或者措施。例如User类型的Name、Password属性,SignIn和SignOut方法,就都是与目的相关的,要调用这一个属性和章程,只可以通过实例化对象来调用,如下所示:
User user = new User();
user.Name = “bruce zhang”;
user.Password = “password”;
user.SignIn();
user.SignOut();

既是最能显示“对象”思想的项目是“类”,我就来介绍一下C#中的类类型。C#中类的第一字是class。在一个class对象中,主要分为field(字段)、property(属性)和method(方法),前边四个照应的是目的的性质,而method则对应对象的表现。一个卓越的class定义如下所示:
public class User
{
 private string m_name;
 private string m_password;
 private int m_tryCounter;
 public string Name
 {
  get {return m_name;}
  set {m_name = value;}
 }
 public string Password
 { 
  get {return m_password;}
  set {m_password = value;}
 }
 public void SignIn()
 {  
  if (m_tryCounter < 3)
  {
   if (IsValid())
   {  
    m_tryCounter = 0;
    Console.WriteLine(“User {0} was signed in.”, m_name);
   }
   else
   {
    m_tryCounter++;
    Console.WriteLine(“User {0} is invalid. Can’t Sign in.”, m_name);
   }
  }
  else
  {
   Console.WriteLine(“You try to sign in more than 3 times. You are be
denied.”);
  }
 }
 public void SignOut()
 {
  m_tryCounter = 0;
  Console.WriteLine(“User {0} was signed out.”, m_name);
 } 
 private bool IsValid()
 {
  if (m_name.ToUpper() == “ADMIN” && m_password == “admin”)
  {
   return true;
  }
  else
  {
   return false;
  }
 }
}

不过,大家在定义类的积极分申时,也可以动用static关键字,定义一些与目标意况无关的类成员,例如上面的代码:
public class LogManager
{
 public static void Logging(string logFile,string log)
 {
  using (StreamWriter logWriter = new StreamWriter(logFile,true))
  {
   logWriter.WriteLine(log);
  }
 }
}
主意Logging为static方法(静态方法),它们与类LogManager的对象情形是井水不犯河水的,由此调用那几个法狗时,并不须求创设LogManager的实例:
LogManager.Logging (“log.txt”,”test.”);

字符串m_name,m_password,m_tryCounter就是类User的字段,Name,Password是类User的属性,而SignIn、SignOut和IsValid则是类User的方法。

所谓“与目的处境无关”,还索要从实例化谈起。在对一个类类型进行实例化操作的时候,实际上就是在内存中分红一段空间,用以创立该目的,并蕴藏对象的一些值,如Name和Password等。对同一个类类型,若是没有非凡的限定,是足以而且创造多个对象的,这几个目的被分配到分化的内存空间中,它们的类型就算同样,却拥有区其余目的情况,如内存地址、对象名、以及对象中种种成员的值等等。例如,大家得以同时创建三个User对象:
User user1 = new User();
User user2 = new User();

至于field,property和method,我会在此后的小说中介绍,这里关键介绍的是在这么些类中冒出的修饰符public、private等相关的知识。

鉴于Name和Password属性是和对象紧密有关的,方法SignIn和SignOut的落到实处也调用了其中的Name和Password属性值,由此也和目的紧密有关,所以这个分子就不可能被定义为静态成员。试想一下,即使把Name和Password属性均设置为静态属性,则设置其值时,只可以采用如下形式:
User.Name = “bruce zhang”;
User.Password = “password”;

面前说到目标好比是一个积木,设计者须要定义好那几个积木的外观和形象,也要考虑积木内部的炮制,例如拔取的材质,以及是空心依旧真诚。若是将这几个积木剖开来看,实际上该对象应分为内、外两层。由于使用者只关注外部的贯彻,由此设计者就需求考虑,哪些完成应暴光在外,哪些落成应隐藏于内。那就突显了对象的卷入的思考。

同理可得,此时设置的Name和Password就与实例user非亲非故,也就是说无论创造了略微个User实例,Name和Password都不属于那一个实例,那肯定和User类的意义相悖。对于艺术SignIn和SignOut,也是一律的道理。当然我们也足以转移方法的定义,使得该措施可以被定义为static,如下所示:
public class User
{
 public static void SignIn(string userName, string password)
 {
  //代码略
}
 public static void SignOut(string userName, string password)
 {
  //代码略
}
}

包裹对象,并非是将整个对象完全包裹起来,而是按照具体的内需,设置使用者访问的权位。在C#中,分别用修饰符public,internal,protected,private设定,分别修饰类的字段、属性和章程,甚至于类对象自我:
public:注明所有目的都能够访问;
protected
internal:申明同一个先后集内的对象,或者该类对象以及其子类可以访问;
internal:注解唯有同一个先后集的目的足以访问;
protected:表明唯有该类对象及其子类对象可以访问;(关于后续,会在后来介绍)
private:声明只有对象自我在对象内部可以访问;

鉴于SignIn和SignOut方法要求调用的Name和Password值改为从章程参数中流传,此时那七个主意就与对象的情形没有其他涉及。定义好的静态方法的调用形式略有分化:
User user = new User();
user.Name = “bruce zhang”;
user.Password = “password”;
User.SignIn(user.Name, user.Password);
User.SignIn(user.Name, user.Password);

能够看到,public的开放性最大,其次是protected
internal,private的开放性最小。internal和protected居中。那么,internal和protected哪一个绽放范围更大呢?我以为,没有完全相对的下结论。它们的界定前者浮现一个横向的定义,后者则反映纵向的概念。借使是internal,那么外部程序集对象自然无法访问,但假诺是处在同一个先后集中,则持有目标都得以访问它;如若是protected,那么固然是外部程序集对象,只要它继续了该对象,就足以访问,而即便是同样程序集,即便目的不是此类对象的子类,也是不可以访问的。打一个只要,在我们的传统文化中,是分外强调“宗族”观念的,一个宗族的族长,对于本族人而言,权力极大,甚至左右了生杀大权。以一个州府的限定为例,internal就好比是长史大人,只即使该州府的赤子,都属于她的管辖范围,而不管他是哪一个宗族。protected则好比是宗族的族长,只借使以此宗族的积极分子,都要听从他,哪怕该成员属于其余州府。我原先看过《雍正帝王朝》,其中就有诸如此类一个内容,身为皇子的胤祯,竟然不能挽救自己热爱女孩子的气数,因为那一个女生违反了她们宗族的族规,最后眼望着他被活活烧死,却不得不黯然泪下,梦里萦回。

两相相比,那样的改动反而导致了运用的不便宜。因而,当一个艺术与对象的情况有较紧密的关联时,最好不要定义为静态方法。

往日边定义的User类而言,所有的字段m_name,m_password,m_tryCounter都是private的,因而User类的外表调用者不可以调用它们,但请留意User类内部的点子比如SignIn或者性质Name,却完全可以调用。同样的,private方法IsValid,可以被SignIn方法调用,但对其余部调用者而言,则是力不从心调用的。而对于public属性Name,Password,public方法SignIn和SignOut,外部的调用者是可以访问的。在后边的排戏中,大家能够看出那里面的区分。通过如此分层次的包装,就可以足够保障对象的重用性和安全性。

那么为何在LogManager类中,我将Logging方法均定义为静态方法呢?那是因为该方法与对象意况没有太大的涉及,如果将艺术的参数logFile和log定义为LogManager类的习性,从实际上利用上也不创立,同时也会造成使用的不便利。最重点的是,一旦要调用非静态方法,不可防止的就须求创立实例对象。那会促成不需求的内存空间浪费。毕竟LogManager类型对于调用者而言,仅在于其Logging方法,而和目的的场地并未太大的关联,因而并不必要为调用这几个办法专门去成立一个实例。那或多或少是和User类型是完全差其余。

这就是说对于类类型而言,怎么着规定它们的拜访权限呢?那要基于实际的急需来看了。假定那个User类是用于一个电子商务网站。那么电子商务系统在设计进程中,就要求调用到User类对象。明显,登录与退出职能是必须提须求外部使用者的,例如登录页面就会选用到User类。而IsValid()方法用于声明用户的合法性,即便也要命须要,但该作用仅仅用于登录的时候核实用户身份,也就是说,IsValid方法只会被SignIn方法应用,但表面实用者却并不关切,因而,设置为private就是合理合法的。同样的道理,字段m_tryCounter也是这样。但假若急需爆发变更,验证用户的功效不仅仅是登录的时候须求利用,在丰裕商品到购物车,下订单,付款的时候,都必要该意义,那么IsValid方法,就有必不可少修改为public方法了。

在一个类类型的定义中,既可以允许静态成员,也可以允许非静态成员。但是在一个静态方法中,是不容许直接调用同一类型的非静态方法的,如下所示:
public class Test
{
 private void Foo1()
 {
  //代码略;
 }
 public static void Foo2()
 {
  Foo1();  //错误;
 }
 public void Foo3()
 {
  Foo1();  //正确;
 }
}

故此,在规划程序的时候,除了要考虑识别对象,还要充裕考虑该对象的包裹。类对象内的字段、属性和办法,包涵类本身,哪些相应揭示在外,哪些应该被埋伏,都亟待依照实际的急需,给与正确的筹划。

在静态方法Foo2中,直接调用了一样类型Test下的私家非静态方法Foo1,将会时有爆发错误;而非静态方法Foo3对Foo1的调用则不利。如要在静态方法Foo2中科学调用Foo1方法,必须创建Test类的实例,通过它来调用Foo1方法,修改如下:
 public static void Foo2()
 {
  Test test = new Test();
  testFoo1();  //正确;
 }

演练:
(一)设计类User,并调用该类
1、打开Visual Studio.Net,选择“File”菜单的“new”,选择“Project”;
2、选择Visual C# Projects中的“Console
Application”。在Location中,定位你要保存的连串的路径,而名字则为“SecondExample”。该名字此时既是缓解方案的名字,同时也是该类型的名字。
3、用鼠标右键单击项目名,在弹出的对话框中,将Assembly
Name命名为SecondExample,将Default Namespace命名为:BruceZhang.com.
SecondExample。
4、用鼠标右键单击项目名,接纳“Add”菜单项的“Add Class”:
 

在Foo2方法中,创立了Test的实例,通过实例对象test来调用Foo1方法。必要专注的是纵然Foo1方法是private方法,但鉴于Foo2方法本身就在Test对象中,所以此时的村办方法Foo1是可以被调用的,因为对象的包装仅针对外部的调用者而言,对于项目内部,即便是private,也是足以被调用的。
 
对此项目的静态属性成员而言,具有和静态方法一样的界定。毕竟,从根本上说,类型的性质,其实就是多个get和set方法。

882828九五至尊手机版 1

只要在类中定义了static的字段,有三种格局对其开始化。一是在概念时早先化字段,或者是在项目标构造器中为这么些静态字段赋予开端值。例如:
class ExplicitConstructor
{
private static string message;
public ExplicitConstructor()
   {
message = “Hello World”;
   }
   public static string Message
   {
     get { return message; }
   }  
}
class ImplicitConstructor
{
private static string message = “Hello World”; 
public static string Message
   {
     get { return message; }
   } 
}

5、在弹出的对话框中,将文件的名字命名为User.cs,如图:
 

在类ExplicitConstructor中,是行使构造器为静态字段message开端化值,而在类ImplicitConstructor中,则是直接在概念时初始化message静态字段。就算那二种办法均可达至早先化的目标,但后者在性质上有鲜明的优势(有兴趣者,可以翻阅我博客上的一篇小说http://wayfarer.cnblogs.com/archive/2004/12/20/78817.html)。因而,我提出当必要开首化静态字段时,应直接初始化。

882828九五至尊手机版 2

即使对于静态字段未设置值,.Net会付出警告,并基于项目的分化赋予不一样的起始值。其余,static还足以和readonly结合起来使用,定义一个只读的静态变量。但是static不能利用到常量的定义中。

6、点击“Open”按钮后,项目中就添加了一个新的公文User.cs。打开该公文,将public
class User中的内容,修改为后面文中定义好的User类。
7、修改原有默许的Class1.cs(要是是Visual Studio
2005,则默认为Program.cs)文件名为App.cs,然后将文件内容改动为:
 class App
 {
  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main(string[]882828九五至尊手机版, args)
  {
   User user = new User();
   
   //用户名和密码均错误;
   user.Name = “Bruce”;
   user.Password = “test”;
   for (int i=0;i<=4;i++)
   {
    user.SignIn();
   }
   user.SignOut();

在C#
1.x中,static并无法用来修饰类类型,也就是说,咱们不可以定义一个静态类。然则对于一个类类型,假设其成员均为静态成员,则此时实例化该类是平昔不意思的。此时,大家平日将构造器设置为private,同时将其类设置为sealed(sealed表明该类不可一连,关于sealed会在前面介绍)。那样就可以免止对类的实例化操作,如前方定义的LogManager,即可以修改定义:
public sealed class LogManager
{
 private LogManager()
 {}
 public static void Logging(string logFile,string log)
 {
  using (StreamWriter logWriter = new StreamWriter(logFile,true))
  {
   logWriter.WriteLine(log);
  }
 }
}

   //用户名正确,密码错误;
   user.Name = “admin”;
   user.Password = “test”;
   for (int i=0;i<=4;i++)
   {
    user.SignIn();
   }
   user.SignOut();

C# 2.0帮衬静态类的定义,方法是在类前边加上static关键字,如:
public static class LogManager{}

   //用户名和密码正确;
   user.Name = “admin”;
   user.Password = “admin”;
   for (int i=0;i<=4;i++)
   {
    user.SignIn();
   }
   user.SignOut();

出于静态类不辅助实例化操作,因而在静态类的定义中,不容许再添加sealed或abstract关键字,也差距意继承某个类或被某个类继承,而类的成员中,也只好是静态成员,且无法定义构造器。由于不存在类的延续关系,因而,静态类成员中,也不允许有protected或protected
internal作为走访限制修饰符。

   //注意此时是无力回天调用那样的字段和章程的;
   //user.m_name;
   //user.m_password;
   //user.IsValid();

   Console.ReadLine();
  }
 }
8、运行。

相关文章

Your Comments

近期评论

    功能


    网站地图xml地图