用C#实现封装(幕课网)

第一节 封装

C #中的类和对象

  • 在VS中,F9设置断点,然后F5运行,之后F11进行断点的语句。F11如果运行到其他的类的方法中,会自动跳转。
  • 字段:就是我之前理解的定义了变量的意思。

C# 属性的封装

  • 属性:对字段进行了封,字段的访问修饰符是private。
    封装的快捷方式:选中字段(变量),然后CTRL+R+E,字段的访问修饰符自动变,调用字段的地方也自动变。
 //public 公共的     private 私有的(默认的)
        private string _name;//姓名字段,访问修饰符是private

        /// <summary>
        /// 姓名属性
        /// </summary>
        public string Name {
            get { return _name; }//读访问器,注意有分号
            set { _name = value; }//写访问器,注意有分号
        }
  • get方法是读,set方法是写,如果去掉set方法,那么就变成了只读属性,如果想为属性赋值,有两种方法,直接为字段赋值,或者通过构造方法赋值。
  • 通过set方法,对属性的赋值进行约束,例如:
        public int Age
        {
            get
            {
                return age;
            }

            set
            {
                if(value<=7 && value>=3)
                age = value;
            }
        }

C# 方法

  • 方法的使用(无参):1、声明方法(方法名,小括号,大括号)。2、调用方法(通过类来调用)。例如:
//在Child 类中声明(定义)了两个方法PlayBall()和EatSugar()
class Child{
  public void PlayBall() {//方法的使用有两步:1、声明方法  
    Console.WriteLine("踢足球");
  }
  public void EatSugar() {
    Console.WriteLine("我很喜欢吃糖");
  }
}
class Kindergarten{
  stativ void Main(string[] args){//程序入口主方法
    Child xiaoMing = new Child();//实例化一个对象,通过对象调用方法
    xiaoMing.PlayBall();//2、调用方法,通过类来调用
    xiaoMing.EatSugar();
  }
}
  • 方法的使用(有参):1、声明方法 (有形参)。2、调用方法(传递实参,类型的数量要对应)。
class Child{
  public void EatSugar(string sugar){//一个字符串类型的无参
    if(sugar == "榴莲糖"){
      Console.WriteLine("我不喜欢吃榴莲糖!");
    }elae{
      Console.WriteLine("太好了,我喜欢吃"+sugar+"糖!");
    }
  }
}
class Kindergarten{
  static void Main(string[] args){
    Child xiaoMing = new Child();
    xiaoMing.EatSugar("棉花糖");//实参的类型,和个数要与方法声明的无参的类型和个数一样
  }
}
  • 方法的重载:在同一个类中,有多个同名的方法,方法的参数个数或者类型至少要有一项不一样,否则无法通过编译。例如:
class Child{
  public void EatSugar(string sugar){//string 类型的参数1个
    Console.WriteLine("你喜欢吃的是"+sugar+"糖!?");
  }
  public void EatSugar(int count){//int 类型的参数1个
    Console.WriteLIne("你今天已经吃了"+count+"块糖了吧?");
  }
  public void EatSugar(string sugar, int count){//string 类型的参数有1个,int 类型的参数有1个
    Console.WriteLine("你已经吃了"+count+"块"+sugar+"了!!!");
  }
}
  • return的作用,当方法执行到return,方法就停止了。
  • return的另一个作用,是返回值,声明方法的时候要指定返回值类型,这个类型必需与return返回的值的类型一致。

对比以下两例子,一个直接输出,另一个将结果返回到调用处由调用处进行处理。返回到调用处更好,因为结果可以由调用处决定用来做什么。

  • 方法直接输出内容,调用方法不能与对方法运算的结果进行操作了:
public void Add(int a,int b){
  int sum = a + b ;
  Console.WriteLine("{0}+{1}={2}",a.b.sum);
}
  • 方法返回结果给调用处使用,运算结果在调用处可以使用,注意方法声明的时候指定的返回类型要与return返回的类型一致:
public int Add(int a,int b){
  int sum = a + b ;
  return sum ;
}

C# 构造方法

  • 无参构造方法:如果不设置,则将默认无参隐式存在。
    1.作用之一是为属性赋值。
    2.如果设置了有参的,隐式的无参将不存在。
    3.构造方法的唯一一种调用方式:new Child(),Child为类名。
    4.通常声明为pulic类型。
    5.返回值类型不用说。
    6.构造方法可以重载,构造方法名与类同名。
public Child(){
  Name = "周星星" ;
}
  • 有参构造方法为属性赋值:
    有访问器的条件下,我们是这样通过构造方法为属性赋值的:

Child类:

class Child{
  public Child(string name,string sex,int age){
    Name = name ;
    Sex = sex  ;
    Age = age ;
}
  private string _name;//姓名
  private string _sex ;//性别
  private int _age ;//年龄

  //_name访问器
  public string Name{
    get{ return _name ; }//注意分号
    set{ _name = value ; }
  }
  //_sex    _age访问器类似,省略
}

Kindergarten主类:

class Kindergarten{
  static void Main(string[] args){
    Child xiaoMing = new Child("小明","男",6);//参数个数、类型、位置都要对应
    Console.WriteLine("大家好,我叫"+xiaoMing.Name);//值就放在xiaoMing.Name变量里了
    //其他属性调用类似
  }
}
  • this 关键字,表示当前对象,如果存在重名,则用于区分是哪个字段,属性,或者方法。命名不冲突可以不使用。
  • 构造方法的重载。与普通的方法重载一样,找到对应的参数的进行调用。需要注意的就是,如果你手动定义了构造方法,默认的无参构造方法就会不再存在了。
  • 对象初始化器:使用的是无参构造方法,无参构造方法必须存在。在实例化对象的时候,在后面增加一双大括号。代码如下:
  Child xiaoMing = new Child(){Name = "小白"};//小括号可以不要,大括号后要有分号

C# 值类型和引用类型

  • 值类型:int char double bool 之类的,创建副本是重新复制一份出来,修改副本则仅更改此副本的值,其他的值不受影响。
  • 引用类型:类,数组,接口,string类型,创建副本时只是将其存储的地址复制一份,指向的是同一个内存空间,修改任何一个副本所有的值都会改变。

值类型:

int x =10 ;
int y = x ;
y++ ;
//更改了 y 的值, x 的值不受影响。
Console.WriteLine(x);//10
Console.WriteLine(y);//11

引用类型:

Child xiaoMing = new Child();//实例化一个对象
xiaoMing.Name = "小明";  // xiaoMing 对象的 Name 属性为小明
Child xiaoYong = xiaoMing ;  // 将 xiaoMing 对象赋值给 xiaoYong ,只是将 xiaoMing 的地址复制一份给 xiaoYong,指向的是同一块内存空间.
xiaoYong.Name = "小勇" ;// 在 xiaoYong 对象更改 Name 属性
//更改其中一个副本的值,其他副本也会受到影响
Console.WriteLine(xiaoMing.Name);//小勇
Console.WriteLine(xiaoYong.Name);//小勇
  • 结构
    1.class 是类,是引用类型。 struct 是结构,是值类型。
    2.结构体中可以有字段、属性、方法。
    3.结构体不可以直接为字段赋值。
    4.结构体不能显式设置无参构造方法,有参构造方法必须为所有的字段初始化,是字段,不是属性。
    5.可以不用实例化结构,注意重载方法的使用,要传递一样的参数才会调用。在Main方法的前面就进行了声明。
    6.结构也可以调用方法。

结构体的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Kindergarten
{
    struct Dog   //class是引用类型    struct是值类型
    {
        string _name;//结构可以有字段
        int _age;//第二个字段
        //_age = 10 ;  不能为字段初始值

        public string Name//结构可以有属性
        {
            get
            {
                return _name;
            }

            set
            {
                _name = value;
            }
        }

        public int Age
        {
            get
            {
                return _age;
            }

            set
            {
                _age = value;
            }
        }

        public void Sing() {//结构可以有方法
            Console.WriteLine("汪汪");
        }
        //public Dog() { }  结构不能显示定义无参构造方法,并且在调用构造方法中要为所有的属性赋值
        public Dog(string name, int age) {
            this._name = name;//必须要为所有的字段都赋值,
            //Name = name;//需要对字段赋值后才能使用对象
            this._age = age;
        }
    }
}

调用结构体的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Kindergarten
{
    class Program
    {
        static Dog dog;//在这个位置声明
        static void Main(string[] args)
        {
            //Dog dog = new Dog();//可以不用实例化对象
            dog.Name = "小白";
            dog.Age = 1;
            Console.WriteLine(dog.Name+dog.Age);
            dog.Sing();//也可以调用方法
            
        }
    }
}
  • 枚举类型,是一种值类型。
    1.不能定义字段、属性、方法。
    2.作用是限定变量的取值范围,提供一组有限的值,值的索引是从0开始递增的。
    3.枚举类型和整型能够相互之间进行类型转换。

在一个单独文件中定义枚举:

enum GenDer {
    男,女     //男的下标是0,女的下标是1。结尾不能有分号
}

从此GenDer 就当是一种数据类型来使用。如:

  GenDer sex1 ;
  sex1 = (GenDer).0 ;   //将0 强制转换成GenDer 类型
  GenDer sex2 ;
  sex2 = GenDer.男 ;  //两种使用方法。
  • 方法参数中的值类型和引用类型
    1.按引用传递,形参改变,实参也会改变。
    2.按值传递,形参改变,实参没有改变。

实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Kindergarten
{
    class Program
    {
        
        static void Main(string[] args)
        {
            Child c1 = new Child("小明",(GenDer)1,12);
            //Growth(c1);//按引用传递
            Growth(c1.Age);//按值传递
            Console.WriteLine("我现在"+c1.Age+"岁了!");//查看原来的值有没有改

        }

        static void Growth(Child c) {//接收的是对象,按引用传递
            c.Age++;//改变Age的值
            Console.WriteLine("1长大了一岁");
        }

        static void Growth(int age) {//接收的是整形,按值传递
            age++;
            Console.WriteLine("2长大了一岁");
        }
    }
}
  • ref关键字:使按值传递的参数改为按引用传递。
    注意:属性或引器不能作为out或ref的参数传递
    实例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Kindergarten
{
    class Program
    {
        
        static void Main(string[] args)
        {
            int age = 3;
            Growth( ref age);//属性或引器不能作为out或ref的参数传递
            Console.WriteLine("我现在"+age+"岁了!");//4

        }
        static void Growth(ref int age) {//接收的是整形,按值传递
            age++;
        }
    }
}
  • out 关键字:
    在形参中指定了这个就是用来返回的,return只能返回一个值,out可以返回多个值.实参上也需要指明是out,接收的变量不需要初始化.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Kindergarten
{
    class Program
    {
        
        static void Main(string[] args)
        {
            int age = 3;
            int ly, ny;//去年年龄,明年年龄
            Growth(age,out ly,out ny);//out关键字声明的变量是用来接收out的输出的
            Console.WriteLine("我今年"+age+"岁了!");//今年年龄
            Console.WriteLine("我去年" + ly + "岁了!");
            Console.WriteLine("我明年" + ny + "岁了!");
        }
        
        static void Growth(int age,out int lastYear,out int nextYear) {//out关键字指明变量是用来输出的
            //lastYear = age--;//去年是今年少一岁,错误的做法
            //nextYear = age++;//明年是今年加一岁,错误的做法
            lastYear = age - 1;//正确做法,不会更改age的值
            nextYear = age + 1;
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容