zoukankan      html  css  js  c++  java
  • 【原创】C#中级教程学习笔记002-面向对象编程

     其他路径:

    CSDN: https://blog.csdn.net/wodehao0808

    微信公众号:程序喵星人

    更多资源和视频教程,QQ:1902686547

    2. 面向对象编程

            面向对象编程也叫做OOP编程。

            简单来说面向对象编程就是结构化编程,对程序中的变量结构划分,让编程更清晰。

    2.1 类和对象

    2.1.1 类

            类实际上是创建对象的模板,每个对象都包含数据集合,并提供了处理和访问数据的方法。

            类定义了类的每个对象(称为实例)可以包含什么数据和功能。

            类中的数据和函数称为类的成员。

                    数据成员

                    函数成员

            数据成员:

                    数据成员是包含类的数据--字段,常量和事件的成员。

            函数成员:

                    函数成员提供了操作类中数据的某些功能。(方法,属性,构造方法和终结器(析构方法),运算符,和索引器)。

             字段的声明

                    访问修饰符 类型 字段名称;

            方法的声明

                    访问修饰符 返回值类型 方法名称(参数)

                    {

                            //方法体

                    }

    2.1.2 对象

            类创建的变量叫做对象。

            实例化一个对象:

                    ClassName myClass = new ClassName();

            其中ClassName是我们定义的类的名字,myClass是我们声明的变量(对象)的名字,后面的new是一个关键字,使用new 加上类型名()表示对该对象进行构造,如果不进行构造的话,这个对象是无法使用的。

    2.1.3 Example: 类和对象

    2.1.3.1 Customer.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace Lesson_2_1

    {

        // 定义一个新的类型(类):Customer

        class Customer

        {

            // 字段,数据成员

            public string name;

            public string address;

            public int age;

            public string buyTime;

            // 方法,函数成员

            public void Show()

            {

                Console.WriteLine("名字:" + name);

                Console.WriteLine("年龄:" + age);

                Console.WriteLine("地址:" + address);

                Console.WriteLine("购买时间:" + buyTime);

            }

        }

    }

    2.1.3.2 Program.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    // 类和对象

    namespace Lesson_2_1

    {

        class Program

        {

            static void Main(string[] args)

            {

                // 如果要使用一个类的话,要先引入它所在的命名空间;

                // 因为Customer位于当前的命名空间下,所以不需要引入,就可以直接使用Customer类;

                Customer ctm;  // 使用 Customer 模板,声明了一个变量(对象)

                ctm = new Customer();  // 对象初始化

                ctm.name = "张三";

                Console.WriteLine("ctm对象的name = " + ctm.name);

                ctm.Show();  // 调用对象的方法

                Console.ReadKey();

            }

        }

    }

    2.2 类的定义和声明

            定义一个车辆(Vehicle)类,具有Run、Stop等方法,具有Speed(速度)、MaxSpeed(最大速度)、Weight(重量)等域(也叫做字段)。

            定义一个向量(Vector3)类,里面有x,y,z三个字段,有取得长度的方法,有设置属性(Set)的方法。

    2.2.1 Example: 类的定义和声明

    2.2.1.1 Vehicle.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace Lesson_2_2

    {

        class Vehicle

        {

            public float speed;

            public float maxSpeed;

            public float weight;

            public void Run()

            {

                Console.WriteLine("这辆车正在以 {0}m/s 的速度行驶", speed);

            }

            public void Stop()

            {

                speed = 0;  // 车子停下来

                Console.WriteLine("这辆车已经停止了,当前速度是:" + speed);

            }

        }

    }

    2.2.1.2 Vector3.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace Lesson_2_2

    {

        class Vector3

        {

            public float x, y, z;

            public float GetLength()

            {

                return (float)Math.Sqrt(x * x + y * y + z * z);

            }

        }

    }

    2.2.1.3 Vector3_2.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace Lesson_2_2

    {

        class Vector3_2

        {

            // 一般情况下,都是将字段设为 private 权限

            // private: 可以在类内部访问,但不可以在外部通过对象直接访问

            private float _fX, _fY, _fZ;

            // 通过提供公有方法去改变私有字段的值

            public void SetX(float p_fX)

            {

                _fX = p_fX;

            }

            public void SetY(float p_fY)

            {

                _fY = p_fY;

            }

            public void SetZ(float p_fZ)

            {

                _fZ = p_fZ;

            }

            public float GetLength()

            {

                return (float)Math.Sqrt(_fX * _fX + _fY * _fY + _fZ * _fZ);

            }

        }

    }

    2.2.1.4 Program.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    // 类的定义和声明

    namespace Lesson_2_2

    {

        class Program

        {

            static void Main(string[] args)

            {

                // 车辆

                Vehicle vh = new Vehicle();

                vh.speed = 60;

                vh.Run();

                vh.Stop();

                // 向量Vector3

                Vector3 vec = new Vector3();

                vec.x = 1;

                vec.y = 1;

                vec.z = 1;

                Console.WriteLine("向量Vector3的长度 = " + vec.GetLength());

                // 向量Vector3_2

                Vector3_2 vec2 = new Vector3_2();

                // vec2._fX = 1;  // private字段,不能在类外部通过对象直接访问

                // vec2._fY = 1;

                // vec2._fZ = 1;

                vec2.SetX(1);

                vec2.SetY(1);

                vec2.SetZ(1);

                Console.WriteLine("向量Vector3_2的长度 = " + vec2.GetLength());

                Console.ReadKey();           

            }

        }

    }

    2.3 构造函数

            构造函数就是用于初始化数据的函数。

            声明基本的构造函数的语法就是声明一个和所在类同名的方法,但是该方法没有返回类型。

            public class MyClass

            {

                    public MyClass()  // 构造函数

                    {

                            这个构造函数的函数体

                    }

            }

            当我们使用new关键字创建类的时候,就会调用构造方法。

            我们一般会使用构造方法进行初始化数据的一些操作。

            构造函数可以进行重载,跟普通函数重载是一样的规则。

            注意:

                    当我们不写,任何构造函数的时候,编译器会提供给我们一个默认的 无参的构造函数,但是如果我们定义了一个或者多个构造函数,编译器就不会再提供默认的构造函数。

    2.3.1 Example:构造函数

    2.3.1.1 Vector3.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace Lesson_2_3

    {

        class Vector3

        {

            private float _fX, _fY, _fZ;

            // 当我们声明一个构造函数后,编译器不会再为我们提供一个默认的构造函数了

            public Vector3()

            {

                Console.WriteLine("这是一个无参的构造函数");

            }

            // 构造函数重载

            public Vector3(float p_fX, float p_fY, float p_fZ)

            {

                Console.WriteLine("这是一个有参的构造函数");

                this._fX = p_fX;  // 也可以 _fX = p_fX;

                this._fY = p_fY;  // 也可以 _fY = p_fY;

                this._fZ = p_fZ;  // 也可以 _fZ = p_fZ;

                // this 就是调用该方法的对象

            }

            public float GetLength()

            {

                // this 就是调用该方法的对象

                return (float)Math.Sqrt(this._fX * this._fX + this._fY * this._fY + this._fZ * this._fZ);

            }

            public void SetX(float p_fX)

            {

                this._fX = p_fX;

            }

            public void SetY(float p_fY)

            {

                this._fY = p_fY;

            }

            public void SetZ(float p_fZ)

            {

                this._fZ = p_fZ;

            }

        }

    }

    2.3.1.2 Program.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    // 构造函数

    namespace Lesson_2_3

    {

        class Program

        {

            static void Main(string[] args)

            {

                // 使用无参构造函数

                Vector3 vec = new Vector3();

                vec.SetX(1);

                vec.SetY(1);

                vec.SetZ(1);

                Console.WriteLine("无参构造函数,向量长度 = " + vec.GetLength());

                // 有参构造函数

                Vector3 vec2 = new Vector3(1, 1, 1);  // 可以发现,使用有参构造函数,可以对字段进行初始化;构造函数的主要作用,也是用于初始化数据;

                Console.WriteLine("有参构造函数,向量长度 = " + vec2.GetLength());

                Console.ReadKey();

            }

        }

    }

    2.4 属性的定义

    2.4.1 属性的定义

            属性的定义结构:

            public int MyIntProp{

                    get{

                            // get code

                    }

                    set{

                            //set code

                    }

            }

            1,定义属性需要名字和类型

            2,属性包含两个块 get块和set块

            3,访问属性和访问字段一样。当取得属性的值的时候,就会调用属性中的get块,所以get块,需要一个返回值,返回值的类型就是属性的类型;当我们去给属性设置值的时候,就会调用属性中的set块,我们可以在set块中通过value访问到我们设置的值。

    2.4.2 只读或只写属性

            private string name;

            public string name{

                   get{

                          return name;

                   }

            }

            属性可以只提供一个set块或者get块。

            只读:只提供 get 块。

            只写:只提供 set 块。

    2.4.3 属性的访问修饰符

            public string name{

                   get{

                          return name;

                   }

                // private 修改了属性的访问权限

                   private set{ 

                          name = value;

                   }

            }

    2.4.4 自动实现的属性

            public int Age{get;set;}

            编译器会自动创建private int age字段。

    2.4.5 Example:属性的定义

    2.4.5.1 Vector3.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace Lesson_2_4

    {

        class Vector3

        {

            // C#一般把字段定义为private,然后通过属性访问和修改字段值

            private float _fX, _fY, _fZ;

            // 属性

            public float X  // 属性和函数,一般都是使用大写字母开头

            {

                get { return _fX; }  // get块中的返回值类型,需要跟属性类型保持一致

                set { _fX = value; }  // set块中,默认变量value,访问我们设置的值

            }

            public float Y

            {

                get { return _fY; }

                set { _fY = value; }

            }

            public float Z

            {

                get { return _fZ; }

                set { _fZ = value > 0 ? value : 0; }  // 增加修改保护,例如银行余额不能负数等

            }

            public Vector3()

            {

            }

            public Vector3(float p_fX, float p_fY, float p_fZ)

            {

                X = p_fX;  // 使用属性的set块,修改对应字段的值

                Y = p_fY;

                Z = p_fZ;

            }

            public float GetLength()

            {

                return (float)Math.Sqrt(X * X + Y * Y + Z * Z);  // 使用属性的get块,获得对应的值

            }

            // 只读属性

            private int _iNum = 10;

            public int Num

            {

                get { return _iNum; }

                // 没有set块,表示这个属性是只读的

            }

            // 只写属性

            private int _iCount;

            public int Count

            {

                set { _iCount = value; Console.WriteLine("Count写入的值是:" + value); }

                // 没有get块,表示这个属性是只写的

            }

            // 属性的访问修饰符

            private string _strName;

            public string Name

            {

                get { return _strName; }

                private set { _strName = value; }  // private 修饰符,表示set块是只能在类内部调用,外部无效

            }

            public void SetName(string p_strName)

            {

                Name = p_strName;  // 类内部,可以使用属性Name的set块

            }

            // 自动实现的属性

            public string School { get; set; }  // 编译器,会自动为 属性School 生成相对应的字段 private string school;

        }

    }

    2.4.5.2 Program.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    // 属性

    namespace Lesson_2_4

    {

        class Program

        {

            static void Main(string[] args)

            {

                Vector3 vec = new Vector3(1, 1, 1);

                Console.WriteLine("vec的x是:" + vec.X);

                Console.WriteLine("vec的y是:" + vec.Y);

                Console.WriteLine("vec的z是:" + vec.Z);

                Console.WriteLine("vec的长度是:" + vec.GetLength());

                // 只读

                // vec.Num = 10; // 无法通过属性设置值,因为属性是只读的,没有set块

                Console.WriteLine("vec的只读属性:" + vec.Num);

                // 只写

                // int i = vec.Count;  // 无法通过属性读取属性值,因为属性是只写的,没有get块

                vec.Count = 100;

                // 属性的访问权限

                // vec.Name = "张三";  // 无法通过属性设置值,因为属性的 set块 的权限是private,外部无法直接访问

                vec.SetName("张三");  // 通过额外的函数,在函数中(类内部)去访问该属性的 set块(private权限)

                Console.WriteLine("vec的name是:" + vec.Name);

                // 自动实现的属性

                vec.School = "中学";

                Console.WriteLine("vec的shcool是:" + vec.School);

                Console.ReadKey();

            }

        }

    }

    2.5 匿名类型

            我们创建变量(对象的时候),必须指定类型,其实我们也可以不去指定类型,这个就是匿名类型,我们可以使用var声明一个匿名类型。

            使用var声明的匿名类型,当初始化的时候,这个变量的类型就被确定下来,并且以后不可以修改。

                    var var1 = 34;

    2.5.1 Example:匿名类型

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    // 匿名类型

    namespace Lesson_2_5

    {

        class Program

        {

            static void Main(string[] args)

            {

                // 使用 var 声明匿名类型

                var v1 = 12;  // 根据初始化的值,推导出v1的类型;类型确定后,就不能更改

                //v1 = "张三";  // v1的类型,已经推导确定了,不能再更改

                var pi = 3.14;

                var name = "张三";

                Console.WriteLine("请输入:");

                var s = Console.ReadLine();

                Console.WriteLine("v1 = " + v1);

                Console.WriteLine("pi = " + pi);

                Console.WriteLine("name = " + name);

                Console.WriteLine("s = " + s);

                Console.ReadKey();

            }

        }

    }

    2.6 堆和栈

            堆和栈 : 程序运行时的内存区域。

            我们把内存分为 堆空间 和 栈空间。

            栈空间 比较小,但是读取速度快。

            堆空间 比较大,但是读取速度慢。

    2.6.1 栈

            栈的特征:

                   数据只能从栈的顶端插入和删除。

            把数据放入栈顶称为入栈(push)。

            从栈顶删除数据称为出栈(pop)。

     

    2.6.2 堆

            堆是一块内存区域,与栈不同,堆里的内存能够以任意顺序存入和移除。

     

    2.6.3 GC垃圾回收

            GC Garbage Collector垃圾回收器。

            CLR的GC就是内存管理机制,我们写程序不需要关心内存的使用,因为这些都是CLR帮我们做了。

     

    2.6.4 值类型和引用类型

            类型被分为两种:值类型(整数,bool struct char 小数等) 和 引用类型(string 数组 自定义的类,内置的类等)。

            值类型只需要一段单独的内存,用于存储实际的数据,(单独定义的时候放在栈中)。

            引用类型需要两段内存:

                   第一段存储实际的数据,它总是位于堆中。

                   第二段是一个引用,指向数据在堆中的存放位置。

     

      

            当我们使用引用类型赋值的时候,其实是赋值给引用类型的引用(即在堆中的地址)。

             如果数组是一个值类型的数组,那么数组中直接存储值。如果是一个引用类型的数组(数组中存储的是引用类型),那么数组中存储的是引用(内存地址)。

    2.6.4.1 Example:值类型和引用类型
    2.6.4.1.1 Vector3.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace Lesson_2_6

    {

        class Vector3

        {

            public float x, y, z;

        }

    }

    2.6.4.1.2 Program.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    // 值类型和引用类型

    namespace Lesson_2_6

    {

        class Program

        {

            static void Main(string[] args)

            {

                Test1();

                Test2();

                Test3();

                Test4();

                Test5();

                Console.ReadKey();

            }

            static void Test1()

            {

                int i = 34;     // 值类型,在栈中存储值:34

                int j = 34;     // 值类型,在栈中存储值:34

                int temp = 34;  // 值类型,在栈中存储值:34

                char c = 'a';   // 值类型,在栈中存储值:a

                bool b = true;  // 值类型,在栈中存储值:true110

            }

            static void Test2()

            {

                int i = 34;   // 值类型,在栈中存储值:34

                int j = 234;  // 值类型,在栈中存储值:34

                string name = "my";  // 引用类型,在堆中存储值:my;在栈中存储(即name的值):my在堆中的地址。

            }

            static void Test3()

            {

                string name = "my";

                string name2 = "you";

                name = name2;    // name保存:you在堆中的地址

                name = "baidu";  // name保存:baidu在堆中的地址

                Console.WriteLine("name = {0}, name2 = {1}", name, name2);  

            }

            static void Test4()

            {

                Vector3 v = new Vector3();  // v指向堆1

                v.x = 100;

                v.y = 100;

                v.z = 100;

                Vector3 v2 = new Vector3();  // v2指向堆2

                v2.x = 200;

                v2.y = 200;

                v2.z = 200;

                v2 = v;  // v2指向堆1

                v2.x = 300;  // 将堆1中的变量x的值改为300

                Console.WriteLine("v.x = " + v.x);  // v也是指向堆1的,所以,输出的值是 300

            }

            static void Test5()

            {

                // 如果数组是一个值类型的数组,那么数组中直接存储值;

                // 如果数组是一个引用类型的数组(数组中存储的是引用类型),MAME数组中存储的是引用(即内存地址)

                Vector3[] vArray = new Vector3[] { new Vector3(), new Vector3(), new Vector3() };

                Vector3 v1 = vArray[0];  // v1指向堆1

                vArray[0].x = 100;  // 修改堆1中的x的值

                v1.x = 200;  // 修改堆1中的x的值

                Console.WriteLine("vArray[0].x = " + vArray[0].x);  // vArray[0]是指向堆1的,所以输出值是200

            }

        }

    }

  • 相关阅读:
    CentOS7安装MySQL5.7
    python基础 元组操作
    初识Python Python的历史(转)
    Python基础 基本数据类型
    createEvent 流沙
    GetLogicalDriveStringS获取驱动器根路径 流沙
    监控文件系统用得到的API 流沙
    Windows I/O 操作CreateFile 流沙
    脚本加入域 流沙
    WMI事件 流沙
  • 原文地址:https://www.cnblogs.com/wodehao0808/p/14651490.html
Copyright © 2011-2022 走看看