第四章:定义封装的类类型

就.NET平台而言,最基本的编程结构就是类类型。

类是由字段数据(通常叫做成员变量)以及操作这个数据的成员(构造函数,熟悉,方法,事件等)所构成的自定义类型。

注:类中的字段很少定义为公共(public)的,为了保护状态数据的完整性,最好将数据定义为私有(private)的或是受保护(protected)的.

  public class CDome  {
       public int id;
       private int code;
       protected int pCode;
       public CDome(){}
        public CDome(int MyId)
        {
             id=MyId;
        }
        public void Say(string text)
        {
             MessageBox.show(text);
        }
 }
Class: 定义类的关键字。public:类的访问范围Cdome:类的名字public CDome():类的构造函数

1.使用new关键字来分配对象

对象必须使用new关键字来分配到内存中。如果我们不使用new关键字,兵器在代码中尝试使用变量的话,就会收到编译器错误。

定义分配对象:CDome dome = new CDome();

定义和分配对象分开编写代码:

CDome dome;//只是声明了指向尚未被创建的CDome对象的引用。

dome=new CDome();//通过new 关键字把引用赋给对象后,这个引用才会指向内存中的有效类实例。

2.构造函数


public CDome(){}
public CDome(int MyId)
{
     id=MyId;
}

构造函数,它允许在创建对象时创建其状态。它是类的特殊方法,在使用new关键字创建对象时被间接调用。

特点:构造函数永远不会返回值,且他的名字必须和需要构造的类的名字相同  【public CDome(){}

默认构造(无参构造):

1).把新对象分配到内存中,取保所有字段数据都设置为正确的默认值。·

2).在new类对象时,如果调用了有参构造,那么默认构造就失效了。 CDome dome= new CDome("测试");

自定义构造(有参构造):

让构造函数彼此不同的是构造函数的参数个数和类型。

 3.this关键字

1).this关键字解决当传入参数的名字和类型数据字段名字相同时产生的作用域歧义。

1 public class Say
2 {
3    ppublic int name="";
4   public Say(string name)
5   {
6      this.name=name;
7   }
8 }

2).this关键字会启用只能感应,这样有助于我们快速回忆忘掉的类成员名称以及提高编写代码效率。

3).在静态成员的实现中用this关键字,会产生编译器错误,原因:静态成员在类(不是在对象)级别产生作用,一次在类级别没有当前对象(也就没有this).

3).this关键字其中的一个用法是使用一项名为构造函数链的技术来设计类(当定义了多个构造函数时,这个设计模式就会很有用)。

 1 //代码
 2 public class Say
 3 {
 4   public string name;
 5   public string id;
 6   public Say(){}
 7   public Say(string name){this.name=name;}
 8   public Say(string name,string id){this.name=name;this.id=id;}
 9 }
10 //改为串联构造函数
11 public class Say
12 {
13   public string name;
14   public string id;
15   public Say(){}
16   public Say(string name):this(name,"")17   {18      Console.WriteLine("构造函数逻辑流程(4)");19   }
20   public Say(string name,string id){this.name=name;this.id=id;}//住构造函数
21 }

4).构造函数逻辑流程

(1).通过调用只有单个int的构造函数来创建对象。

(2).构造函数将提供的数据转发给主构造函数,并且提供调用者没有提供的其他出事参数。

(3).主构造函数把传入的数据赋值给对象的字段数据。

(4).控制返回到最初调用的构造函数,并且执行所有剩余的代码语句

5).使用构造函数链的好处是,这种变成模式在任何版本的c#语言和.net平台中都可用的。然而,在使用net4或者更高版本时,你还可以是哟娜可选参数代替传统的函数链,从而大大简化编程任务。

注:可选参数只能在vs2010,.net4及以上版本使用。

 //代码
  public class Say
 {
  public string name;
   public string id;
   public Say(string name,string id=""){this.name=name;this.id=id;}
 }

 4.static关键字

C#类(或结构)可以通过static关键字来定义静态成员,这些成员只能通过类级别调用。

静态成员只能操作静态数据或调用类的静态方法,如果在静态成员中使用非静态类数据或调用类非静态方法,就会受到编译时错误。

静态变量分配一次值,被类的所有实例所共享。

public class Say
{
   public static name="张三";//静态变量   public static Say()//静态构造函数   {       name="李四";
   }
   public static void ToSay()//静态方法
    {
       Console.WriteLine(name);
    }
}

静态构造函数:特殊的构造函数,非常适用于初始化在编译时为止的静态数据值。

1).一个类只可以定义一个静态构造函数。

2).静态构造函数不允许访问修饰符,不能接受任何参数。

3).无论创建了多少类型的对象,静态构造函数只能执行一次。

4).运行库创建类实例或调用者首次访问静态成员之前,运行库会调用静态构造函数。

5).静态构造函数的执行先于任何实例级别的构造函数。

静态类:用static 修饰的类为静态类。静态类不能使用new关键字来创建,且类里只能包含用static关键字标记的成员或字段。

public static class Say
{
   public static name="张三";//静态变量
   public static Say()//静态构造函数
   {
       name="李四";
   }

   public static void ToSay()//静态方法
    {
       Console.WriteLine(name);
    }
}
//类调用:类名.方法
Say.ToSay();

 5.OOP的支柱

所有基于对象的语言(C#,JAVA,C++,Smalltalk 和 VisualBasic等)必须满足OOP的3个核心原则,通常也叫做“OOP的支柱”:封装、继承、多态。

封装:将用户不必了解的实现细节隐藏起来的一种语言能力。

继承:基于已有的类定义来创建新类定义的语言能力。

多态:语言以同一种方式处理相关对象的能力。

6.C#访问修饰符

类型:类、接口、结构、枚举、委托

成员:属性、方法、构造、字段


访问修饰符


可以应用到的地方


作用


public


类型或者类型成员


公共的项没有限制。公共成员可从对象以及任何派生类访问。

公共类型可以从其他外部程序集进行访问。


private


类型成员或嵌套类型


私有项只能由定义它们的类(或结构)进行访问。


protected


类型成员或嵌套类型


受保护项可以由定义他们的类以其任意子类使用,但外部类无法通过c#的点操作符访问。


internal


类型或类型成员


内部项只能在当前程序集中访问。如果我们在.net类库中定义一组内部类型的话,其他程序及就不能使用他们


Protected internal


类型或嵌套类型


如果在一个项上组合protected 和 internal 关键字,项在定义他们的程序集、类以及派生类中可用。

1).默认情况下,类型成员是隐式私有的,类型是隐式内部的。

class Say//默认内部
{
   Say(){}//默认私有
}

2).嵌套类型:直接声明在类或结构作用域中的类型。

public class Say
{
    private enum MyColor//嵌套类型
    {
       Red,Green,Blue
    }

 7.封装

封装概念核心:对象的内部数据不应该从对象实例直接访问,如果调用者想改变对象的状态,就要使用访问方法(即getter)和修改方法(即setter).

黑盒编程:英文名称:black box programming。   对外部世界隐藏操作数据方式的细节。

使用传统的访问方法和修改方法:

public class Say
{
    private string name="";
    public Say(string name)
    {
         this.name=name;//修改方法
    }
    public string GetName()//访问提取name
   {
       return name;
   }
}

使用.NET属性进行封装 (value 表示调用者设置属性时传入的值,该标记不是c#关键字,而是上下文关键字)

public class Say
{
    private string name="";
    public string Name
    {
        get{retrun name;}//获取(访问方法)
        set{name=value;}//设置(修改方法)
    }
}

静态属性

public class Say
{
    private static string name="";
    public static string Name
    {
        get{retrun name;}//获取(访问方法)
        set{name=value;}//设置(修改方法)
    }
}

8.自动属性

在.NET3.5发布的时候,c#语言提供了另外一种使用最少的代码定义简单封装服务的方法,叫做自动属性语法。

自动属性不允许构建只读或只写的自动属性。

自动属性交互:直接调用属性名称(编译时才会定义私有的返回字段)

public class Say
{
       //自动属性:在类中调用直接调用属性名称
       public  string Name{get;set;}
}

9.对象初始化器语法

对象初始化语法只是使用默认构造函数创建类变量并设置各个属性状态数据的语法的简写形式。

public class Say
{
    public Say(string value,string text)
    {
    }
}
//对象初始化器语法调用
Say sShow = new Say{value="1",text="张三"}

初始化内部类型

public class Say
{
   private Point topLeft =new Point();
    public Point TopLeft
    {
        get{retrurn topLeft;}
        set{topLeft=value;}
    }
    public Say(string value,string text)
    {
    }
}
//对象初始化器语法调用 TopLeft内部类型
Say sShow = new Say{TopLeft=new Point{X=10,Y=10},value="1",text="张三"}

10.常量数据(关键字 const)

1).定义常量时必须指定值。

2).常量在调用时不能改变值(只能在定义时赋值)

3).常量是隐式静态的。

4).只读字段:只读字段的值可以在运行时决定,因此在构造函数作用域中进行赋值是合法的。

public class Say
{
    public const double id=3.14;//常量(其他地方不能改变值)
    public readonly double readId;//只读字段    public static readonly double readsId=3.14;//静态只读字段: 如果运行时才知道静态只读字段的值,就必须用静态构造函数
    public Say()
    {
            readId=3.14;//可以在构造函数中为制度字段赋值,其他地方不行
    }    public static Say(){readsId=3.14}//静态构造函数
}

 11.分部类型和分部方法(引用(风尘浪子):https://www.cnblogs.com/leslies2/archive/2011/09/09/2172267.html

在面向对象的“封装闭合性”开发原则中,一向提倡的是把独立的功能封装在一个类里面的!但从Visual Studio 2005开发,系统提供了一个分部类的开发方式一直受到争议,很多人认为把同一类的功能分布不同的文件中,是打破了“封装闭合原则”,一个类的功能变得难以管理,大多数人都是在无奈的情况下才使用到分部类的方式。但在winFrom类、页面类、DataSet里面你经常可以发现分部类的身影,当你用到Entity Framework的时候,你会发现每个映射生成的对象都是使用分部类的方式生成的,分部类似乎早已派上用场。分部类究竟有什么好处,下面为大家一一揭露。

1.分部类

根据微软的定义,分部类就是“将类或结构、接口或方法的定义拆分到两个或多个源文件中。 每个源文件包含类型或方法定义的一部分,编译应用程序时将把所有部分组合起来”。在使用分部类的时候,必须为类加入partial的关键字,注意每个类的可访问性必须一致,其中一类为public,其他类也必须为public。如果其中一个类为抽象类,那合并后整个类都将被视为抽象类,其中一个类为密封类,那合并后整个类都将视为密封类。

 1 publicpartialclass PersonManager 2 { 3     public Person GetPersonById(int id) 4     { 5     } 6 } 7  8 publicpartialclass PersonManager 9 {10     public List<Person> GetList()11     {12     }13 }

在合并的时候,总体类全把所有的基类和特性合并继承。要注意的是分部类必须在于同一个程序集当中,而且关键字不得相冲,如果一个类上为public ,另一个类为private,那将会出错。在第二个分部类中可以调用第一个分部类中所定义的字段与方法。

 1 [SerializableAttribute] 2 public partialclass Person { } 3  4 [ObsoleteAttribute] 5 public partialclass Person { } 6  7 //合并后相当于 8 [SerializableAttribute] 9 [ObsoleteAttribute]10 class Person{ }11 12 13 partialclass PersonManager:Manager{ }14 15 partialclass PersonManager:Collection{ }16 17 //合并后相当于18 class PersonManager:Manager,Collection{ }

 

2).分部方法

分部方法与分部类十分相像,方法必须包含partial关键字,如果一个类中并不包含该方法的实现,而另一个类中实现了该方法,将不会影响这个方法的正常运行。这个特点跟接口有异曲同工之妙,特别是在使用代码生成器的时候,开发人员可以使用工具生成分部方法,然后手动去实现方法。分部方法有以下几个限制,第一方法必须返回void,只能默认为private;第二,分部方法不能为virtual和extern方法;第三,分部方法可以有ref参数,但不能有out参数;

1 partial void PersonChanged(Person person);2 3 partial void PersonChanged(Person person)4 {5       PersonManager personManager=new PersonManager();6       personManager.Update(person);7       ......8 }

关于分部类与分部方法,在微软的官方网站上有着详细介绍,在这里不多作说明。而下面在下想介绍一下分部类与分部方法的实际用途,这才是我写这章文件的真的目的。

 

3).分部类与分部方法的可用性

LINQ是微软在Framewrok3.0开发推出的新产品,其中LINQ TO SQL是实现对象与数据表相映射的神奇工具。随着Framework 4.0面世,Entity Framework成为微软项目中实现ORM的主要手段,当中*.edmx文件中使用的都是分部类的实现方式。这是因为映射过程是自动生成的,代码必须符合定制的规则,当需要为对象添加一些额外的属性,而这些属性无需保存到数据库的时候,分部类就派上用场,我们可以使用分部类为对象提供各种的自定义属性。

特别是在使用DDD领域驱动设计的时候,分部类成为实现模型动作的一个好方法。失血模型与充血模型是DDD长久争议的话题,在失血模型中,模型是不应该具备动作,而是把动作放在Service层中,而在充血模型中,模型类应该具有各自的方法,而“分部类”就是实现充血模型方法的一种好手段。

  1         //Model.Designer.cs文件    2        [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(  3                 NamespaceName="BusinessModel", Name="Approve")]    4        [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]    5        [global::System.Serializable()]    6        public partial class Approve : global::System.Data.Objects.DataClasses.EntityObject    7        {    8            /// <summary>    9            /// 创建新的 Approve 对象。   10            /// </summary>   11            /// <param name="id">ID 的初始值。</param>   12            /// <param name="functionType">FunctionType 的初始值。</param> 13           [global::System.CodeDom.Compiler.GeneratedCode(" 14                    System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   15           public static Approve CreateApprove(int id, int functionType)   16           {   17               Approve approve = new Approve();   18               approve.ID = id;   19               approve.FunctionType = functionType;   20               return approve;   21           }   22           /// <summary>   23           /// 架构中不存在属性 ID 的任何注释。   24           /// </summary> 25           [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute( 26                    EntityKeyProperty=true,IsNullable=false)]   27           [global::System.Runtime.Serialization.DataMemberAttribute()]   28           [global::System.CodeDom.Compiler.GeneratedCode( 29                    "System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   30           public int ID   31           {   32               get   33               {   34                   return this._ID;   35               }   36               set   37               {   38                   this.OnIDChanging(value);   39                   this.ReportPropertyChanging("ID");   40                   this._ID = global::System.Data.Objects.DataClasses 41                                      .StructuralObject.SetValidValue(value);   42                   this.ReportPropertyChanged("ID");   43                   this.OnIDChanged();   44               }   45           }   46           [global::System.CodeDom.Compiler.GeneratedCode(" 47                    System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   48           private int _ID;   49           [global::System.CodeDom.Compiler.GeneratedCode(" 50                    System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   51           partial void OnIDChanging(int value);   52           [global::System.CodeDom.Compiler.GeneratedCode(" 53                    System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   54           partial void OnIDChanged();   55           /// <summary>   56           /// 架构中不存在属性 FunctionType 的任何注释。   57           /// </summary> 58           [global::System.Data.Objects.DataClasses 59                   .EdmScalarPropertyAttribute(IsNullable=false)]   60           [global::System.Runtime.Serialization.DataMemberAttribute()]   61           [global::System.CodeDom.Compiler.GeneratedCode( 62                   "System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   63           public int FunctionType   64           {   65               get   66               {   67                   return this._FunctionType;   68               }   69               set   70               {   71                   this.OnFunctionTypeChanging(value);   72                   this.ReportPropertyChanging("FunctionType");   73                   this._FunctionType = global::System.Data.Objects.DataClasses 74                                               .StructuralObject.SetValidValue(value);   75                   this.ReportPropertyChanged("FunctionType");   76                   this.OnFunctionTypeChanged();   77               }   78           }   79           [global::System.CodeDom.Compiler.GeneratedCode(" 80                    System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   81           private int _FunctionType;   82           [global::System.CodeDom.Compiler.GeneratedCode(" 83                    System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   84           partial void OnFunctionTypeChanging(int value);   85           [global::System.CodeDom.Compiler.GeneratedCode(" 86                    System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   87           partial void OnFunctionTypeChanged();   88           /// <summary>   89           /// 架构中不存在属性 Title 的任何注释。   90           /// </summary> 91           [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]   92           [global::System.Runtime.Serialization.DataMemberAttribute()]   93           [global::System.CodeDom.Compiler.GeneratedCode(" 94                    System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]   95           public string Title   96           {   97               get   98               {   99                   return this._Title;  100               }  101               set  102               {  103                   this.OnTitleChanging(value);  104                   this.ReportPropertyChanging("Title");  105                   this._Title = global::System.Data.Objects.DataClasses106                                        .StructuralObject.SetValidValue(value, true);  107                   this.ReportPropertyChanged("Title");  108                   this.OnTitleChanged();  109               }  110           }  111           ...............................  112      }  113    114      //分部类  115      public partial class Approve  116     {  117             //添加属性  118            public string Type  119            {  120                 get;set;  121            }  122   123           //添加动作  124           public void AddReport(Report report)  125           {.......}  126           .................  127     } 

参考【C# 与 .net 4 高级程序设计(第五版)】整理总结

原文地址:https://www.cnblogs.com/zhangliangliang/p/9120744.html

时间: 2024-11-09 07:23:11

第四章:定义封装的类类型的相关文章

第四章:1.串 -- 串类型定义及串的表示和实现

前言: 计算机上的应用程序几乎都是以字符串数据作为处理对象,然而,现今我们使用的计算机的硬件结构主要是反映数值计算的需要的,因此,在处理字符串数据时比处理整数和浮点数要复杂得多.而且,在不同类型的应用中,所处理的字符串具有不同的特点,要有效地实现字符串的处理,就必须根据具体情况使用合适的存储结构.这一章,我们将讨论一些基本的串处理操作 和 几种不同的存储结构. 目录: 1.串类型的定义 2.串的表示和实现 2.1.定长顺序存储表示 2.2.堆分配存储表示 2.3.串的快链存储表示 3.串的模式匹

软件设计的哲学:第四章 深度封装模块

目录 4.1 模块化设计 4.2什么是接口? 4.3 抽象 4.4 深度模块 4.5浅模块 4.6 类拆分 4.7示例:Java和Unix I/O 4.8 结论 管理软件复杂性最重要的技术之一是系统设计,这样开发人员在任何时候都只需要面对总体复杂性的一小部分.这种方法称为模块化设计,本章介绍其基本原理. 4.1 模块化设计 在模块化设计中,软件系统被分解成一系列相对独立的模块.模块可以采用多种形式,例如类.子系统或服务.在理想的情况下,每个模块都完全独立于其他模块:开发人员可以在任何模块中工作,

SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-010-Introduction为类增加新方法

一. 1.Introduction的作用是给类动态的增加方法 When Spring discovers a bean annotated with @Aspect , it will automatically create a proxy that delegates calls to either the proxied bean or to the introduction implementation, depending on whether the method called be

JAVA基础学习之路(四)定义简单java类

简单java类开发一般原则: 类名称必须有意义,再怎么说,要让人家看的明白吧 类之中所有属性必须使用private封装,并提供setter,getter方法 类之中可以有多个构造方法,但是必须保留有一个无参数构造方法 类之中不允许出现任何输出语句,所有输出必须交给被调用处 类之中需要有一个可以取得对象完整信息的方法,一般叫做getInfo(),返回String型数据 class Book { private String name; private int price; private int

C++ Primer 学习笔记_63_重载运算符和转换 --转换和类类型【上】

重载运算符和转换 --转换与类类型[上] 引言: 在前面我们提到过:能够用一个实參调用的非explicit构造函数定义一个隐式转换.当提供了实參类型的对象须要一个类类型的对象时.编译器将使用该转换. 于是:这样的构造函数定义了到类类型的转换. 除了定义到类类型的转换之外,还能够定义从类类型到其它类型的转换.即:我们能够定义转换操作符,给定类类型的对象.该操作符将产生其它类型的对象.和其它转换一样,编译器将自己主动应用这个转换. 一.转换为什么实用? 定义一个SmallInt的类,该类实现安全小整

C++ Primer 学习笔记_63_重载操作符与转换 --转换与类类型【上】

重载操作符与转换 --转换与类类型[上] 引言: 在前面我们提到过:可以用一个实参调用的非explicit构造函数定义一个隐式转换.当提供了实参类型的对象需要一个类类型的对象时,编译器将使用该转换.于是:这种构造函数定义了到类类型的转换. 除了定义到类类型的转换之外,还可以定义从类类型到其他类型的转换.即:我们可以定义转换操作符,给定类类型的对象,该操作符将产生其他类型的对象.和其他转换一样,编译器将自动应用这个转换. 一.转换为什么有用? 定义一个SmallInt的类,该类实现安全小整数,这个

第四章 复合类型

第四章  复合类型 4.1  数组 4.1.1  数组简介 数组(array)是一种数据格式,能够存储多个同类型的值. 声明数组的通用格式如下: typeName arrayName[arraySize]; 表达式arraySize指定数组的元素数目,它只能是以下三种情况之一: 1)        整型常数(如10,枚举值也可以): 2)        const值 3)        常量表达式(如8 * sizeof(int)) 注意:使用数组要注意下标的正确.编译器不会检查使用的下标是否有

【C++】C++自学旅程(7):类类型初识——类的定义

新年第一博,新年快乐! 一直不明白面对对象的“对象”是什么意思,想象不出:在学OC时出现了奇怪的语法,让程序“自己”运行:EDA的沙龙中提到了类类型,但不知道这是个什么鬼.终于这些问题的谜底要被我自己自学揭开了,哈哈哈!类类型我来啦! 类(Class)是一种自定义数据类型,是具有相同属性和行为的一组对象的集合,它是面向对象中最为重要的概念之一.类类型中有变量来存储属性和数据,叫做成员变量或数据成员,还有操作这些数据的函数,叫做成员函数. 类类型的作用: 实现封装 数据隐藏 继承和派生多态 ……

C#1(.net和C#的关系、VS与.net的对应关系、VS2012常用的几种应用程序、C#定义一个类的方法、类页面内容的解释、定义Person的类、调用Person类的方法、命名规范、数值类型)

1..net和C#的关系 .net是一个开发平台,C#是应用在.net平台上的一种语言.   2.VS与.net的对应关系  3.VS2012常用的几种应用程序 第一种是Windows窗体应用程序,也即是我们常用的C/S端的应用软件: 第二种是控制台应用程序,主要是用来学习调试C#代码的(老师上课应用的模式): 第三种是空Web应用程序,建立空的网页模式,B/S模式: 第四种是Web 窗体应用程序,建立后会生成一些常用的网页组件和功能,例如JS.image等,也是B/S模式. 4.C#定义一个类