C# 属性

封装性

 

  含义

  1. 字段和方法放到一个类中
  2. 类中字段私有化,类中方法公开化

     为私有化的添加一组方法

               获取字段值的方法   Get***()

               设置字段值的方法   Set***()

 

    

  一个私有字段对应一个属性,属性其实有两个方法

  只是在 写法简洁了一些。

 

  class  Role

  {

 

      private   string   roleName ;

      private   int      age ;

 

      public   string   RoleName

      {

          get  {  return   roleName ; }

          set  {  roleName = value  ; }

      }

 

      public    int      Age

      {

            get    {     return  age;   }

            set    {     age = value;   }

 

      }                       

    

  }

 

    Role  r1 =  new Role();

 

    r1 . Age =  -200  ;  

    Console.WriteLine( r1. Age  );

 

  

    属性语法:

      public    返回值类型    属性名

      {

              get {  return   字段名  ;  }

              set {  字段名 =  value  ;  }

      }

   注:1.属性名和字段名是对应的,只是属性名应该首字母大写;

     

       2.一个属性中对应两个方法:get  和  set

         通过get访问字段的值,通过set设置字段的值

 

       3.如何利用属性访问或设置值?

 

         对象名.属性名 = 值 ;//设置值

         对象名.属性名  ;    //访问值

 

       4.将具体值设置到字段上时,有一个隐含的变量value

         是先将具体值交给value变量,再由value变量给

         字段。value的类型会与当前操作的字段匹配。

    

   总结 :

   字段私有化,方法公开化

   一个私有化字段对应一个标准属性(包含两个方法get|set)

 

   练习:

   创建一个单选试题类,类中的字段私有化,方法公开化

   然后为私有化字段添加对应的标准属性。

   通过属性来设置字段值,访问字段值

  

   中午练习:

   为 SingleQuestion.cs 类添加无参数和含有全部(4个)

   的构造方法。

   创建一个 测试类 , SingleQuestionTest2.cs

   在测试类中,创建一道单选试题,对象名为:q2 ,

   在创建这道试题时,通过构造方法的形式为对象的4个

   字段设置值,设置值之后,调用Print()方法打印出这道试题

   然后提示用户输入答案,用户输入答案后,判断用户答案

   与 正确答案是否一致。然后提示“答对了”或“答错了”

  

 

  1.如何实现封装----属性

 

  2. 标准属性

     1)特点

     2)属性的两个方法

     3)属性中的set,对数据进行业务逻辑处理

     4)标准属性可设置 只读操作 ,只写操作

 

        只读:只能访问字段的值,而不能为字段设置值

        只写:只能为字段设置值,设置完值,是不能访问的。

        当然,可以设置只读或只写权限,也可以设置既可读

        也可写。

 

 

   2. 自动属性(了解)

  class Question

  {

      private  int  no  ;  //字段

 

      //标准属性

      public   int   No

      {

          get {   return no ; }

          set {   no = value ;}

      }

 

  }

 

  一个私有字段 + 一个标准属性

  相当于:一个自动属性

         

 

     public   int   No

     {

         get ;

         set ;

     }

  

   练习:

   创建一个Student类

   类中包含两个字段:

      学生姓名 ---- name 字段,标准的属性 Name

      学生学号 ---- 自动属性 No

    

   标准属性和自动属性

   1.自动属性是 prop ,按两次Tab

     不需要再自己定义私有字段,系统会在自动属性中

     自动添加一个对应的私有字段

 

   2.何时使用自动属性?

     编码中,一般都是使用标准属性 。

     但是,如果一个类中有大量的字段(如:50个)

     但是对字段设置值或访问值时,只是做最简单的设置和访问

     而不需要对数据做任何处理(如:比如,数据是否合法)

     这时,就可以使用自动属性。

     这表明,使用属性进行了封装,符合类的设计规则。

 

   3.自动属性get和set必须成对出现,在自动属性 中

     不能再设置只读或只写一种权限;

     自动属性中不能在set中添加业务代码

     对字段的值进行相应判断的操作。

    

 

 

    练习:创建一个多选试题,MultiQuestion.cs,包含的字段:

 

     字段:题号,题干,选项,     答案(多个 )

           no    text  options     answer

 

     方法:Print(): 打印试题到控制台方法   

           Check( string[] inputAnswers ):判断试题正误

           构造方法

 

     要求:字段应该使用自动属性来实现。

 

 

 

      string   answer = "A,B,C" ;

      string[]  ans =  answer .Split( ‘,‘ );

     

----------------------------------------------------------

 

  继承性

 

  提高代码复用性

 

  子父类

 

 

  共有的内容提取出来,作为父类

  其它的类中,如果使用 共有的内容,继承父类

 

 

  单选试题 :题号,题干,选项,答案(1个 )

             构造方法

             Print()

             Check( string inputAnser)

 

  多选试题: 题号,题干,选项,答案(多个)

             构造方法

             Print()

             Check( string[] inputAns)

 

 

  1. C# 中的继承,子父类关系

  2. C# 中的继承符号: 冒号

     子类类名的后面加上冒号,冒号跟的是一个父类的类名

 

  3.C#中的继承是单层继承

 

  4.C#中的继承具有传递性

    class  A     {   }  --- 爷爷 A

    class  B : A {   }  --- 父亲 B

    class  C : B {   }  --- 儿子 C 

 

    C类继承了B类,C就具备了B类的所有内容,

    B类又继承了A类,B类就具备了A类的所有内容,

 

    而对于C来说,C类不光具备了B类的内容,

    同时,隐式的具备了A类中的内容。

   

  5. 子类继承了父类,可以继承父类的哪些内容?

     ---全部内容都会被子类继承

     当然,全部内容有一些比较特殊的:

 

     1) 父类私有的内容:

         表面上看,是访问不到,但是实际是继承了

         只是暂时访问不到。

         将来,可以通过反射等操作拿到相关数据  )

 

     2) 父类的构造方法

         构造方法是不能继承的,但是可以子类可以使用

         (??????)

 

   6. 如果父类有了内容,子类又定义了相同的内容,

      用子类对象调用时,究竟会调用谁的?

 

      virtual    override   new     base

  

 

   ------------------------------------------------------

 

 

   总结:

   1.封装性

     封装的意义

     如何实现封装?

     标准属性

     自动属性 (了解)

    

   2.继承性

     继承性的意义

     继承的基础语法

     继承的基本特点

     继承中的关键字: vitural override new  base

    

    

 

作业1:

   上课代码,SingleQuestion.cs

             MultiQuestion.cs

             Test.cs

   要求:创建单选试题,多选试题,然后提示用户输入

   答案,并判断结果。

 

   作业2:

   创建试题类,父类,Question.cs

     --题号,题干,选项

     --构造方法(无参数构造方法,含有三个参数构造方法)

       打印试题到控制台方法Print()

 

   创建单选试题类,SingleQuestion.cs

      -- 继承了试题类,

      -- 添加自己特性的内容:

         private  string   answer;

         Check( string answer )

      要求:字段私有化,为私有化字段添加标准属性

 

   创建多选试题类,MultiQution.cs

      -- 继承了试题类,

      -- 添加自己特性的内容:

         private  string[]   answer;

         Check( string[] answer )

      要求:字段私有化,为私有化字段添加标准属性

 

    创建测试类。

   

 

 

 

 

day11  (2019.4.16) (2018.01.15.Tuesday)

属性

 

  day11         2018.01.16         周二    

----------------------------------------------------------

  

   封装性:如何设计一个类

 

 

   继承性:如何实现代码重复利用

       继承基本内容:

       1)子父类
       2):
       3)单层继承
       4)传递性
       5)全部继承(私有,构造方法)

 

       6)构造方法
       7) virtual  override   new

         

     virtual : 父类方法返回值前加 virtual

     override: 子类方法返回值前加 override

     表示继承了父类的中的某些方法,方法不是特别适合子类,

     子类就可以在 继承过来的基础上,再进行适当的重新修改,

     “重写”。

 

 

     new     : 当父类和子类都有相同的方法,子类明确

               表示不想使用父类的方法,并且不想继承父类

               的这个方法,这时,需要在子类的这个方法

               最前面加:new,表示隐藏父类相同名字的方法。

--------------------------------------------------------    

    练习:测试new关键字的使用场景

    创建一个类库项目,创建一个 工具类,工具类一个

    方法: public  void  ShowClassMessage()

 

    创建一个 项目,项目下一个类,项目中需要导入一个第三方

    类库, 类中定义了一个和类库中同名的方法,如何操作 ?

   

    1.代码详见:“new关键字的使用”文件夹下内容

  

    2.详细步骤:

 

    1) 创建了一类库项目   .net framework

 

    2)  类库项目下创建一个类,ClassUtils.cs

        类中添加一个方法: ShowClassMessage()--一句话

 

    3) 右击类库项目 --- 生成

        注:找到生成的 .dll 的文件(当前类库项目所在目录

        --bin---Debug--****.dll )

    4) 将***.dll文件拷贝到桌面

 

    5) 创建一个普通的控制台应用程序

        导入桌面上的  .dll文件  : 右击引用--添加引用--浏览

    6) 控制台项目中创建一个类,NewDemo.cs

        继承 .dll 类库中的某个类( ClassUtils.cs)

        继续NewDemo.cs中添加一个 方法:ShowClassMessage()--

 

    7) 编译期间:给出绿色的警告信息:

        是否需要显示的隐藏父类中的方法,使用new关键字

       

     练习:创建图形类,Shape

           字段:名字 name

           方法:求周长和求面积的方法(定义时定义为虚方法)

                 构造方法

          

           创建图形类的子类:矩形类Rectangle

               ---字段:width ,height

                  构造方法  

           圆形类:Circle,

               -- 字段:radius 半径

                  构造方法

           要求:子类中对求周长和面积的方法进行重写。

 

  代码详见:DAY11_02_OOP05

              

 -------------------------------------------------------    

父类 子类构造方法调用先后

     当创建一个子类对象时,先进入子类构造方法

     在子类每个构造方法的小括号后面,其实都默认省略了

     :base(),先调用父类的无参数构造方法,然后才是

     子类当前的构造方法。

    

     1) 不写:base(),调用父类无参数

     2)  写 :base(), 调用父类无参数

     3) 写  :base( *** )调用父类对应形式的构造方法

 

     上面所有内容说明:

     ----创建子类对象,一定会先调用父类相应的构造方法----

     ----调用父类无参数的还是有参数的,有几个参数的,

         取决于子类构造方法小括号后面使  :base(参数)

    

 

     继承关系中的构造方法负责的工作:

         有时候,创建对象时通过构造方法为字段赋值,

         有些字段是继承父类得来的,在子类中直接为字

         些字段赋值是不可取的,如何破?

         ---谁的字段交给谁初始化(赋值)----

         如果是父类的字段,就要使用:base()的形式

         让父类自己去赋值。

         子类的特性内容,让子类自己赋值。

 

   练习:为单选试题类添加含有4个参数的构造方法,

         其中前3个参数(题号,题干,选项)应该交给父类的

         的构造方法去完成(即:使用 :base(,,,)

         然后为父类添加含有3个参数的构造方法,

         最后创建一个测试类,测试类中创建一道单选试题,

         要求:创建试题时,通过构造方法为试题的字段赋值。

         然后打印这道试题(只打印,不用输入答案判断)

 

   代码详见:DAY11_01_OOP5 项目

 

 

   中午练习:  

  在当前类的基本上,补全“矩形类”:

  1) 矩形类添加字段:长和宽,width ,height

  2)  为字段添加2个标准属性

  3) 重 写父类的求周长和求面积的方法。

      矩形周长:2*(长+宽)。  矩形面积:长*宽

  4) 创建一个测试类,测试类中创建矩形对象,然后

      通过属性为字段赋值,打印矩形的 周长和面积

 

  在“Shape”图形类中添加无参数构造方法和含有一个参数构造

  在“Circle”圆形类中添加无参数,含有2个参数的构造方法

  其中第一个参数表示图形的名称,这个参数要交由父类赋值

  另外一个参数就是当前圆的半径,这个参数子类自己赋值。

  矩形类也是类似的,不再详细描述。 

  创建测试类,通过构造方法为对象赋值,测试周长和面积。

 

  代码详见:DAY11_01_OOP5 项目下的:

        Shape.cs

        Circle.cs

        Rectangle.cs

      ShapeTest1.cs--测试创建圆的对象,利用属性为对象赋值

      ShapeTest2.cs--测试创建圆的对象通过构造方法为对象赋值

      ShapeTest3.cs--测试创建矩形对象通过构造方法为对象赋值

 

 

  --------------------------------------------------

  3. base  关键字的使用:

 

   1. 子类构造方法的小括号后面使用:

          :base() 或  :base( 参数列表)

 

   2. 在子类重写了父类的那个方法的 方法体中,   

      使用 base.方法名() 来表示调用父类的方法    

      比如:圆类重写了图形类中的求周长和求面积的方法,

      在圆类中的求面积的方法中,return 后面使用了base.

------------------------------------------------------

   代码详见:DAY11_01_OOP5项目下:

      Circle.cs---GetArea()方法

      BaseTest.cs ---测试类

 

  ---------------------------------------------------------

 

   多态性

 

   1.   Question   q   =  new   SingQuestion();

      

        父类变量,创建子类对象

 

        父类变量指向子类对象

 

        父类引用指向子类对象

 

 

        父类引用引用子类对象

 

       

  练习:创建一个汽车类,Car.cs,父类,作为 父类

        --字段:汽车品牌

        --方法:汽车介绍 Introduce( )

          构造方法(无参数,含有一个参数)

 

        汽车类创建多个子类:

        Benz.cs , 奔驰车

        Audi.cs ,奥迪车

        BMW.cs  , 宝马车

       

        汽车测试类 :CarTest

       

 

   1.向上转型

     使用“父类变量指向子类对象”的方式创建对象的过程

     称为 向上转型。

 

   2.向上转型后,这时,这个对象就具备了2种类型:

     一种类型是:父类型

     另外一种类型: 子类

     根据运行期间对象的所属类型来决定该执行子类还是父 类

     中的方法。如果子类重写了,执行子类自己的,如果子类

     没有重写,执行父类的,如果父类,就会报错。   

 

   如: Car  c  =  new   Benz();

        这时,c 就有两种类型,1种类型是属于:Car 类型

        另外一种类型属于 Benz()类型。

        代码阶段,都属于Car类型,运行期间,会是奔驰类型的。

        

 

  1.   Car  c  =  new   Benz();

       多态

       c.******* ( Car 类中的内容)

       c.Introduce();

      

  2.  向上转型后,对于 c 的两种类型:

       Car类型,Benz类型)

 ------------------------------------------------------- 

    

   多态数组

   方法参数

   方法返回值

  

  

   Person

   {

           public   void  Drive(  Car  c  )

           {

 

           }

   }

 

   Person  p1= new Person();

 

   Car  c  =   new    Benz()  ;

 

   p1.Drive( c );

 

 

 分析: 游戏树V1.0

 

 在这个案例中,是集合了封装、继承、多态的综合案例。

--------------------------------------------------------------

 1.封装体现在:设计4个实体类时,这4个类中的字段和方法进行限制。

   Role -- 角色类

   Magic --魔法师类

   soldier --战士类

  

   要求:类中的字段私有化,然后为私有化字段添加标准属性。

         方法公开化,然后添加构造方法。

 

 2.继承体现在:

   Role  ---- 角色类,父类

   Magic ---- 魔法师角色,子类

   soldier --- 战士角色,  子类

  

   要求:Role类中定义了角色名称,定义了进攻的方法

   战士类和魔法师类继承了角色类,重写了Role类中的Attack()方法。

   另外,使用了 :base( roleName )显示的调用父类含有一个参数构造

   方法为父类的 roleName 字段赋值。

 

 4. 多态体现在:

    设计  Team 类

 

    Team 类中的成员:

 

    1) 一个Role类型的数组,存储团队中的多名不同的角色

        注:该数组既可以存储魔法师成员,又可以接收战士角色的成员

            最多只能包含6个成员,如果超过,给出错误提示。

 

    2) void AddMemeber( Role r )

        该方法用于向Role数组中添加角色成员。

        这里的参数为 Role 类型,这样保证了只要使用父类变量指向

        子类对象的方式创建对象,将对象传给 参数 r时,r就能正常

        接收。也就是:r 保证了可以接收多种类型的角色(魔法师或战

 

   3)  int AttackSum():获取整个团队中的总伤害值

       该方法中遍历Role数组,获取数组中每个角色成员对敌人的

       进攻伤害值,所有角色成员伤害值相加,就是最后结果。

 

       遍历 Role数组时,使用数组中的每个元素调用 Attack()

       会根据具体 角色 来 选择执行Attack()

       当数组成员为Magic时,且Magic中重写了父类的Attack()

       方法,那么编译器会执行Magic类中的Attack(),而不会执行

       父类Role类中的Attack();

       同样,如果角色成员 为soldier时,且soldier 重写了Attack()

       会调用子类自己的Attack()方法。

 

  最后:要求组建一个团队,并创建多个成员,然后将成员通过

        AddMember()方法添加到团队中。添加之后,调用

        AttackSum()方法,计算整个团队进攻时,整个团队的

        整体攻击伤害值。

C# 属性

上一篇:P3620 [APIO/CTSC 2007]数据备份[优先队列+贪心]


下一篇:api接口统一封装