C#基础- 构造函数和析构函数-11

我爸骑着摩托车,后面坐着我妈,我妈抱着我。
走在一个小路上时,前面突然闯出来一个货车,眼看就要撞上了,我爸突然喊了句
“快把孩子丢出去”
我妈当机立断把我丢到路旁的泥潭。

结果,摩托刹住了,货车也刹住了
我满脸泥巴懵逼的看着他们


========================手动分割线==========================
练习:定义一个矩形类(Rectangle),
成员变量:width,height,
XYPoint类型的point(原始点),
XYPoint类型的center(中心点)。
方法:封装变量为属性,构造方法初始化成员变量width,height,
计算周长、计算面积(ref/out参数修饰)*/

    //点是一个结构体类型
    public struct XYPoint
    {
        public double x;
        public double y;

        public XYPoint(double a, double b)
        {
            x = a;
            y = b;
        }
    }
    //定义一个矩形类,里面有四个字段和四个属性
    public class Rectangle
    {
        private double width;
        private double height;
        private XYPoint originalPoint;
        private XYPoint centerPoint;
        //带有参数的构造函数对字段进行初始化
        public Rectangle(double w, double h, XYPoint o, XYPoint c)
        {
            width = w;
            height = h;
            originalPoint = o;
            centerPoint = c;
        }

        public double Width
        {
            get { return width; }
            set { width = value; }
        }

        public double Height
        {
            get { return height; }
            set { height = value; }
        }

        public XYPoint OriginalPoint
        {
            get { return originalPoint; }
            set { originalPoint = value; }
        }

        public XYPoint CenterPoint
        {
            get { return centerPoint; }
            set { centerPoint = value; }
        }
        //周长
        public void Perimeter()
        {
            double peri = (this.Height + this.Width) * 2;
            Console.WriteLine("矩形的周长是:{0}", peri);
        }
        //面积
        public void Square()
        {
            double squ = this.Width * this.Height;
            Console.WriteLine("矩形的面积是:{0}", squ);
        }
    }
  • 在Main方法中添加如下:
    XYPoint a = new XYPoint(4, 5);
    XYPoint b = new XYPoint(5, 6);
    Rectangle rec = new Rectangle(23, 34, a, b);
    rec.Perimeter();
    rec.Square();

一、构造方法和析构方法

1.1构造方法 -- 负责开辟内存空间,初始化对象

1.构造方法的方法名必须和类名一致
2.构造方法没有返回值,不需要写void
3.构造方法能够添加参数
4.构造方法允许重载
5.如果没有给类添加构造方法,系统会提供一个默认的构造,也就是只开辟空间
6.如果将某个构造方法设为私有的,就不允许再通过这个构造创建对象

using System;
//面向对象
namespace LessonPrepare09
{
    class Student
    {
        // 字段
        public string name;
        public int age;

        public Student()
        {
            // 默认的构造方法,只开辟空间
            Console.WriteLine("这是默认的构造方法");
        }

        // 重载构造方法,给方法添加参数,在初始化的同时完成赋值操作
        public Student(string _name)
        {
            name = _name;
        }

        private Student(int _age)
        {
            age = _age;
        }
        public Student(string _name, int _age)
        {
            name = _name;
            age = _age;
            Console.WriteLine("这是带参数的构造方法");
        }

1.2析构方法 -- 在对象销毁时调用,用于释放内存

1.每个类只能有一个析构方法
2.析构方法不能有返回值
3.析构方法不能有访问权限修饰符
4.析构方法不能带有参数,更不能重载
5.析构方法只能由系统自动调用,不能手动调用

        ~Student()
        {
            Console.WriteLine("执行了析构方法");
        }
    }

练习1:创建一个教师类,特征:姓名、性别、教课内容,内建构造方法初始化所有特征。

    class Teacher
    {
        public string name;
        public string gender;
        public string className;
        public Teacher(string _name, string _gender, string _className)
        {
            name = _name;
            gender = _gender;
            className = _className;
        }
        ~Teacher()
        { }
    }

练习2:创建一个学生类,特征:学号,姓名,当前授课老师,内建构造方法初始化所有特征。

    class Student
    {
        public string name;
        public int number;
        public Teacher tea;
        public Stu(string _name, int _number, Teacher _tea)
        {
            name = _name;
            number = _number;
            tea = _tea;
        }
        ~Stu()
        { }
    }
    在Main方法中添加如下代码
    // 使用默认的构造方法初始化一个对象
      Student stu1 = new Student();
    // 单独为各个字段赋值
      stu1.name = "老王";
      stu1.age = 18;
      Console.WriteLine("我是{0}, 今年{1}岁", stu1.name, stu1.age);
            
    // 使用带参数的构造方法初始化一个对象,此时不需要单独为字段赋值
      Student stu2 = new Student("老汉", 40);
    Console.WriteLine("我是{0}, 今年{1}岁", stu2.name, stu2.age);
    //这样会报错
//    Student stu3 = new Student (10);
//    Console.WriteLine (stu3.age);

二、面向对象

  • 面向过程:以事件为中心,关注的是完成事件的详细步骤,一步一步该怎么实现.

  • 面向对象:以事物为中心,关注的是每个事物具备的特征和行为,而完成该事件只是事物所有功能的几个小功能而已.

  • 面向对象的两个核心概念:
    类:具备相同特征和行为的事物的抽象,就是一个数据类型.是抽象的概念
    对象:类的实例,类的具体表现,生活中的万物都是对象,相当于变量,占用内存空间

  • 面向对象的优点:重用性、灵活性和扩展性

  • 面向对象的三大特性:封装、继承、多态

  • OO:面向对象

  • OOP:面向对象编程

  • OPP:面向过程编程

三、面向对象的特性

3.1 封装

封装是面向对象的第一步
封装就是将数据、方法等集合在一个个单元中,我们称之为类
封装的意义在于保护代码、护具,屏蔽复杂性

    // 定义一个Person类
    class Person
    {
        /**

        */
        // 添加一个私有的字段
        string name;
        // 为外界提供访问私有字段的接口
        public void SetName(string _name)
        {
            Console.WriteLine("Person类的方法");
            name = _name;
        }

        public string GetName()
        {
            Console.WriteLine("Person类的方法");
            return name;
        }
    }
    注释掉之前定义的Student类

3.2 继承

  • 继承的优势:就是省代码,增强程序的可扩展性、可修改性和可复用性.
  • 继承的上层:基类,继承的下层:派生类.
  • 如果创建类时没有指定基类,默认都是继承自Object(根类)
  • 继承具有传递性.C继承自B,B继承自A,则C拥有A与B的全部内容.
  • C# 只支持单继承,即派生类只能有一个直接基类
  • 派生类获得基类的所有方法、字段、属性和事件
  • 派生类可以赋值给基类,但是基类不能赋值给派生类
  • 使用场景:当多个类都具有多个相同的字段和方法时,可以将公共部分定义成父类,供其他类去继承
  • 通过在派生的类名后面追加冒号和基类名称,可以指定基类
    // 定义一个学生类,继承自Person类
    class Student : Person // 表示Student类继承自Person类 
    {
        // 为派生类添加自己的字段和方法
        private int number;
        // 学号
        public int Number
        {
            set
            {
                Console.WriteLine("Student类的方法");
                number = value;
            }
            get
            {
                Console.WriteLine("Student类的方法");
                return number;
            }
        }
    }
    在Main方法中添加如下代码
    // 在Student类中不添加任何代码,就可以具有父类的方法
    Student stu = new Student();
    stu.SetName("张三");
    Console.WriteLine("stu的名字是:" + stu.GetName());
    stu.Number = 101;
    Console.WriteLine(stu.GetName () + "的学号是:" + stu.Number);

   // 派生类可以赋值给基类,但是基类不能赋值给派生类
   //  Person per = new Student ();
   //  Student stu1 = new Person ();//会报错
  • 在刚才创建的Student类的下方创建练习
    练习:定义一个大学生类,继承自学生类,添加独有的属性和方法
    class CollegtStu : Student
    {
        // 添加属性:专业
        string subject;

        public string Subject
        {
            get
            {
                return subject;
            }
            set
            {
                subject = value;
            }
        }
        // 添加方法:玩游戏
        public void PlayGames()
        {
            Console.WriteLine("学生时期有很多的时间玩游戏");
        }
    }
    在Main方法中创建大学生对象,使用父类的方法设置姓名SetName
    // 定义一个大学生对象,使用父类的方法设置姓名
     CollegtStu college = new CollegtStu();
     college.SetName("小明");// 继承的传递性
     Console.WriteLine(college.GetName () + "是名大学生");

3.3 多态(添加一个新文件Polymorphic,写多态的代码)

在新添加的文件中添加如下代码
using System;
namespace Polymorphic
    {
        // 定义一个枪类,继承自根类,添加属性和方法
        class Gun
        {
            // 瞄准
            public void Loaded()
            {
                Console.WriteLine("开枪前需要先瞄准");
            }

            // 开枪
            public virtual void Fire()
            {
                Console.WriteLine("嘣!");
            }
        }
        // 定义一个AK47类,继承自Gun
        class AK47 : Gun
        {

3.3.1方法替换 -- 在子类中重新实现父类中定义的方法,使用关键字new

            public new void Loaded()
            {
                Console.WriteLine("AK47还需要瞄准?");
            }

3.3.2虚方法和重写

  • 虚方法 -- 多用于实现多态(使用父类类型,调用子类中实现的方法)
  • 用virtual修饰的方法叫做虚方法,用 override修饰的方法叫做重写
  • 只有方法和属性才能是虚,字段不能虚
  • 在父类中使用关键字 virtual,在子类中重写父类中定义的方法,使用关键字 override
            public sealed override void Fire()
            {
                Console.WriteLine("AK47,哒哒哒……");
            }
        }

        回到program中的Main方法中(别忘了引入命名空间),添加如下代码
           Gun gun = new Gun();
           gun.Loaded();
           gun.Fire();

           AK47 ak = new AK47();
           ak.Loaded();
           ak.Fire();
注释掉之前创建gun的代码,添加如下代码
            Gun gun = new AK47();// 把子类对象赋值给父类
            gun.Loaded();// 进行了方法替换的,还是调用父类的实现
            gun.Fire();// 进行了方法重写的,就调用子类中的实现
  • 在刚才创建的新文件Polymorphic,添加如下的代码来讲解密闭性

3.3.3 密封类

  • sealed修饰符,修饰类为密封的,不可被继承不可被重写。
  • 派生类可以通过sealed来停止继承,内部的方法可以通过sealed来阻止被重写
  • sealed是对虚方法或虚属性,也就是同override一起使用,如果不是虚方法或虚属性会报出错误
    // 创建一个M56类,继承自AK47
    class M56 : AK47
        {
            // 被sealed修饰的方法,就不能被重写了
            //        public override void Fire() {
            //
            //        }
        }
  • 在创建的新文件Polymorphic,添加如下的代码来讲解一下虚方法和重写
  • 扩展案例,用于理解 虚方法和重写
    class Animal
        {
            public string Name { get; set; }
            public virtual void Eat()
            {
                Console.Write("{0}正在进食 —— ", Name);
            }
        }

        class Sheep : Animal
        {
            public Sheep()
            {
                Name = "羊";
            }
            public override void Eat()
            {
                base.Eat();
                Console.WriteLine("吃草");
            }
        }

        class Tiger : Animal
        {
            public Tiger()
            {
                Name = "老虎";
            }
            public override void Eat()
            {
                base.Eat();
                Console.WriteLine("吃肉");
            }
        }
  • 回到program中的Main方法中,添加如下代码,来查看虚函数效果
        Animal sheep = new Sheep();
        Animal tiger = new Tiger();
        sheep.Eat();// 调用子类重写的方法
        tiger.Eat();// 调用子类重写的方法

本次讲解就到这里,有关技术问题请小伙伴们添加QQ群:941928511,大家一起探讨!
版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,677评论 6 524
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,772评论 3 408
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 173,108评论 0 370
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,378评论 1 303
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,394评论 6 403
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,807评论 1 315
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,127评论 3 432
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 41,136评论 0 281
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,693评论 1 328
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,703评论 3 349
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,810评论 1 357
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,400评论 5 352
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,130评论 3 341
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,532评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,707评论 1 278
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,412评论 3 383
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,892评论 2 368

推荐阅读更多精彩内容