zoukankan      html  css  js  c++  java
  • C#面向对象的概念

    在前面的学习中,我间接提到了一些关于方法,类和面向的对象的一些概念,但是所描述的概念并不是很专业,并且很肤浅。也是鉴于本人水平并不高,如果哪里有错误,也请大家具体指出。

    起初我刚接触到面向对象这个概念时候,感觉和PLC中写的FB块很像,就是将一些数据,和一下业务逻辑封装到一起,组成一个方法

    方便我们重复的使用。稍微有点不同的是,C#中的方法依存于类中,我们要在类中创建方法才有意义。

    我们把这些具有相同属性和相同方法的对象进行进一步的封装,抽象出类的概念。类就是个模子,确定了对象应该具有的属性和方法。对象是根据类创建出来的。

    所有面向对象的编程语言,都是我们吧要处理的“数据”和“行为”(方法)封装到类中。

    类的语法

    [public] class 类名

    {

        字段;

        属性;

        方法;

    }

    写好一个类后,我们需要创建这个类的对象,这个过程为类的实例化。this关键字表示当前类的对象。

    创建流程如下:

    1.设计类:就是根据需求设计各种类,为每一个类设计对应的“数据存储”和“操作内容”

    2.关联类:我们所设计的对象,他们之间是有一定关联的,正是按照这种关系,完成对象的交互。

    3.使用类:根据我们的需要,使用我们所设计的类,使用的时候通过对象的方式调用。

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace 草稿
     8 {
     9     public class Person
    10     {
    11         public string _name;
    12         public int _age;
    13         public char _gender;
    14 
    15         public void CHLSS()
    16         {
    17             Console.WriteLine("我叫{0},我今年{1}岁了,我是{2}生,我可以吃喝拉撒睡~~~",this._name,this._age,this._gender);
    18         }
    19     }
    20 }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace 草稿
     8 {
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             //创建对象
    14             Person LXB = new Person();
    15             LXB._name = "LXB";
    16             LXB._age = -23;
    17             LXB._gender = '';
    18             LXB.CHLSS();
    19             Console.ReadKey();
    20         }
    21     }
    22 }

    类是不占内存的,对象是占内存的。我们在仔细观察上面程序,在实际变成当中,年龄是不许有负数的,是非法的。这时,我们需要引入属性这个概念,他的作用就是保护字段,对字段的赋值和取值进行限定。创建对象要在方法中。

    属性的语法;

    public string Name

    {

        get{return _name;}

        set{_name=value;}

    }

    属性的使用:

    作用:在OOP中主要用来封装数据。

    要求:一般采用Pascal命名法,数据类型和字段要一致,使用public修饰。

    其实C#发展至今,属性的语法写法如下:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace 草稿
     8 {
     9     public class Ticket
    10     {
    11         //C#2.0时代标准属性
    12         private double _distance;
    13 
    14         public double Distance
    15         {
    16             get { return _distance; }
    17             set { _distance = value; }
    18         }
    19 
    20         //C#3.0时代,对标准属性做了简化(以后,标准属性,都可以这样用)
    21         public int Price { get; set; }      
    22 
    23         //C#4.0时代,增加属性表达式(下面写法不常用)
    24         private double unitPrice=4000;
    25         public double UnitPrice { get => unitPrice; set => unitPrice = value; }
    26 
    27         //C#4.0时代以后,可以直接赋值。
    28         public string Type { get; set; } = ".Net开发系列";
    29 
    30     }
    31 }

    在这几种方法中,没有显示写出对应的私有字段,编译器都会帮我们自动生成。可以通过reflector查看。

    属性的本质就是两个方法,一个叫get(取值)一个叫set(赋值)。在我们实际应用中,不是所有属性都有get和set方法,要过呢据实际情况而定。外界不能随便访问到我们的字段,所以更改如下

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace 草稿
     8 {
     9     public class Person
    10     {
    11         private string _name;
    12         public string Name
    13         {
    14             get { return _name; }
    15             set { _name = value; }
    16         }
    17 
    18         private int _age;
    19         public int Age
    20         {
    21             get { return _age; }
    22             set
    23             {
    24                 if (value<0||value>100)
    25                 {
    26                     value = 0;
    27                 }
    28                 _age = value;
    29             }
    30         }
    31 
    32         private char _gender;
    33         public char Gender
    34         {
    35             get { return _gender; }
    36             set { _gender = value; }
    37         }
    38 
    39         public void CHLSS()
    40         {
    41             Console.WriteLine("我叫{0},我今年{1}岁了,我是{2}生,我可以吃喝拉撒睡~~~",this.Name,this.Age,this.Gender);
    42         }
    43     }
    44 }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace 草稿
     8 {
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             //创建对象
    14             Person LXB = new Person();
    15             LXB.Name = "LXB";
    16             LXB.Age = 23;
    17             LXB.Gender = '';
    18             LXB.CHLSS();
    19             Console.ReadKey();
    20         }
    21     }
    22 }

    当我们创建好一个类的对象后,要给这个对象的每个属性去赋值,这个过程叫对象的初始化。

    读取:属性通过get方法,返回私有字段。

    赋值:属性通过set方法,借助value给私有字段赋值。

    本质:属性本身其实并没有保存数据,而字段才是真正数据的存储单元。在属性get和set方法中添加业务逻辑。

    对象创建,成员变量的定义,可以在类中直接定义。但是对象属性的使用,方法的调用,必须放到方法中。 

    总结:属性和字段

    字段(成员变量)

    (1)内部使用:字段主要是为类的内部数据交互使用,字段一般为private.

    (2)数据存储:字段只是用来存储数据,如果不是静态数据,生命周期和对象共存亡。

    (3)读写不限:我们可以给字段赋值,也可以获取字段的值(readonly除外)。

    属性(字段封装)

    (1)外部使用:属性一般是向外提供数据访问,属性是public修饰,用来对外表示对象的静态特征。

    (2)业务扩展:属性内部可以添加我们需要的业务逻辑,可以避免非法数据,或完成其他相关任务。

    (3)读写可控:属性可以根据需要设置为只读属性,更好地体现面向对象的“封装特性”!也就是安全性!

    使用

    (1)常规化使用:对象本身的“对外”数据保存,都是通过属性完成的,调用者都可以使用

    (2)强制性使用:公有化字段,在很多时候是无法被解析的。(比如dgv,combobox的显示问题)。


    静态方法和非静态方法区别

    (1)在非静态类中,既可以有实例成员,也可以有静态成员。

    (2)在调用实例成员的时候,需要使用对象名.实例成员。

         在调用静态成员的时候,需要使用类名.静态成员名。

    总结:静态成员必须使用类名去调用,而实例成员使用对象名。静态函数中,只能访问静态成员,不允许访问实例成员。

    1)如果想要将你的类当作一个“工具类”,可以考虑将类写成静态类。

    2)静态类在整个项目中资源共享。(静态存储区)只有在程序全部结束轴,静态类才会释放资源。

    在给对象初始化的时候,我们可以用构造函数。

    构造函数是一个特殊的方法

    (1)构造函数没有返回值,连void都不能有。

    (2)创建对象的时候会执行构造函数。

    (3)类当中会有一个默认的无参的构造函数,当你写一个新的构造函数之后,不管有参无参,那个无参的构造函数都会被干掉。

    this关键字的作用:

    1.代表当前类的对象。

    2.在类当中显示嗲用本类的构造函数。:this

    析构函数的概念:

    当程序结束的时候,析构函数才能执行。帮助我们释放资源。

    下面我们做一个练习:写一个Ticket类,有一个距离属性(只读),在构造方法中赋值。不能为负数,有一个价格属性,并根据距离distance计价Price(1元/公里)

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace 草稿
     8 {
     9     public class Ticket
    10     {
    11         private double _distance;
    12 
    13         public double Distance
    14         {
    15             get { return _distance; }
    16         }
    17 
    18         private double _price;
    19 
    20         public double Price
    21         {
    22             get
    23             {
    24                 if (_distance>0 && _distance<= 100)
    25                 {
    26                     return _distance * 1.0;
    27                 }
    28                 else if (_distance>=101 && _distance<200)
    29                 {
    30                     return _distance * 0.95;
    31                 }
    32                 else if (_distance>=201 && _distance<300)
    33                 {
    34                     return _distance * 0.9;
    35                 }
    36                 else
    37                 {
    38                     return _distance * 0.8;
    39                 }
    40             }
    41         }
    42 
    43         public Ticket(double distance)
    44         {
    45             if (distance<0)
    46             {
    47                 distance = 0;
    48             }
    49             this._distance = distance;
    50         }
    51 
    52         public void ShowTicket()
    53         {
    54             Console.WriteLine("{0}公里需要{1}元",Distance,Price);
    55         }
    56 
    57 
    58     }
    59 }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace 草稿
     8 {
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             Ticket t = new Ticket(90);
    14             t.ShowTicket();
    15             Console.ReadKey();
    16         }
    17     }
    18 }

     C#构造方法的补充

    构造方法的作用:

    因为构造方法是在对象创建的时候被调用的,所以,我们在创建的时候,可以完成一些初始化的任务。

    初始化:包括给对象的属性赋值,或从其他对象,文本等获取基础数据。

    构造方法的类型:

    (1)无参数的构造方法:一个类中,如果没有显示的写出构造方法,编译器会默认生成一个无参的构造方法。我们也可以 随时显示添加一个无参数的构造                        方法。通常是用来直接初始化对象的属性或“某些不变的数据”。

    (2)有参数的构造方法:让对象创建者,自己传递要初始化的相关数据。

    对象初始化器的使用

    引入:C#3.0时代开始

    作用:更加灵活的初始化对象的“属性”

    语法:

     对象类型 对象名=new 对象类型()

    {

           成员名1=value1,

           成员名2=value2,

    }

    构造方法

    1)存在的必要性:一个类中,至少要有一个构造方法。(可以无参数,也可以有参数的)

    2)调用的特殊性:只能在对象创建的时候,通过new关键字调用。

    3)使用的强制性:对象的创建,必须调用指定的构造方法,也就是参数必须统一。

    4)语法的特殊性:不能有返回值,构造方法必须和类名一样。

    构造方法PK对象初始化器

    相同点:都可以完成对象“属性”初始化

    不同点:1.有无强制性:构造方法有强制性,对象初始化器没有强制性,随意使用。

            2.使用的范围:对象初始化器只能完成属性初始化,而构造方法可以完成任何需要的初始化任务。

            3.使用的位置:对象初始化器在创建对象的时候使用,而构造方法必须提前写在类中。

            4.出现的时间:构造方法在.Net1.0版本就有,而对象初始化器只能在.Net3.0以上版本才能使用。

    注意:成员变量和局部变量同名时,一般实就近原则取变量,如果我们舍近求远,则必须添加this。


    对象的生存周期

    对象在内存中不断的“生生死死”,具有生命周期。

    对象在内存中的状态

    正在引用:程序正在使用对象。

    游离状态:没有引用对象,已经使用完毕但依然占用空间。

    我们可以显示的清除对象的引用,也就是仅为一个变量名,没有具体对象指向。对象名称=null

    托管运行环境下对象的销毁由虚拟机负责,析构函数没多大用途。

  • 相关阅读:
    day 66 crm(3) 自创组件stark界面展示数据
    day 65 crm(2) admin源码解析,以及简单的仿造admin组件
    用 Python+nginx+django 打造在线家庭影院
    django -admin 源码解析
    day 64 crm项目(1) admin组件的初识别以及应用
    云链接 接口不允许 情况 解决方法 mysql Host is not allowed to connect to this MySQL server解决方法
    day 56 linux的安装python3 ,虚拟环境,mysql ,redis
    day55 linux 基础以及系统优化
    Codeforces 989 P循环节01构造 ABCD连通块构造 思维对云遮月参考系坐标轴转换
    Codeforces 990 调和级数路灯贪心暴力 DFS生成树两子树差调水 GCD树连通块暴力
  • 原文地址:https://www.cnblogs.com/LiyuLi/p/12166549.html
Copyright © 2011-2022 走看看