面向对象编程

面向对象编程是很重要的编程思想,先简单介绍一下。

面向对象编程(object-oriented programming)简称OOP技术,是开发应用程序的一种新方法、新思想。过去的面向过程常常会导致所有的代码都包含在几个模块中,使程序难以阅读和维护。对软件修改时常常牵一动百,使以后的开发和维护难以为继,而使用OOP技术,常常需要使用许多代码模块,每个模块有自己的特定功能,它们是彼此独立的。这样就提高了代码重复使用的几率,更利于软件的开发、维护和升级。

在面向对象中,形象店来说,对象=(算法+数据结构),程序等于(对象+对象+对象+。。。。。。)

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

在介绍面向对象三大特征之前先引入类的概念:

类是对象概念在面向对象编程语言中的反映,是相同对象的集合。类描述了一系列在概念上有相同含义的对象,并为这些对象同意定义了编程语言上的属性和方法。

类是C#中功能最为强大的数据类型,像结构一样,类定义了数据类型的数据和行为。然后,开发者可以创建此类的实例的对象。类支持继承,而继承是面向对象编程的基础部分(注:C#中类只支持单继承)

类通过关键字class来声明:

1 类修饰符 class 类名
2 {
3 }
4 //声明一个简单的类
5 public class Car
6 {
7     public int number;//编号
8     public string color;//颜色  
9 }

之前介绍了字段和属性,他们也是构成一个类的一部分。
构造函数和析构函数是类中比较特殊的两种成员函数。主要用来对对象进行初始化和回收对象资源,也就是说对象的生命周期从构造函数开始,以析构函数结束。

构造函数书是在创建给定类型的对象时执行的类方法,而且构造函数的名称必须和类的名称相同。写一个最简单的构造函数并调用它如下

    class Program
    {
        private int x = 3;
        private int y = 4;
        private int z = 0;
        public Program()
        {
            z = x + y;
        }
        static void Main(string[] args)
        {
            Program pr = new Program();
            Console.Write(pr.z);
        }
    }

构造函数可以有参数可以没有参数,没有参数的构造函数就是默认构造函数,不管在什么时候,只要用new关键字实例化对象,并且不为new提供任何参数,就会调用默认构造函数。

析构函数用~加类名命名。.NET Framwork类库有垃圾回收功能,当某个类的实例被认为不再有效,并符合析构条件。.NET Framework 类库的垃圾回收功能就会调用该类的析构函数实现垃圾回收。

注意:一个类中只能有一个析构函数,并且无法调用析构函数,它是被自动调用的,一个简单的析构函数如下

 class Program
    {
        ~Program() //析构函数
        {
            Console.Write("析构函数自动调用");//输出一个字符串
        }
        static void Main(string[] args)
        {
            Program pr = new Program();
        }
    }

对象的声明和实例化,这个很简单其实就是用new关键字进行实例化。实例化了一个对象,然后对对象进行操作。
注意:在没有对类进行实例化前,无法用类名调用类中的方法或字段。不实例化调用方法参考static。

说到这可能还对类和对象的概念很模糊:类和对象的区别就是,类是具有相同或相似结构、操作和约束规则的对象组成的集合;而对象是某一个具体化的实例,每一个类都使具有某些共同特征的对象的抽象。(类是一种抽象的数据类型,而对象是一个类的实例)

通俗点来讲一个类可以有很多个对象,用代码来说。

class Program
    {
        static void Main(string[] args)
        {
            Program pr = new Program();//pr是Program类的一个对象。
            Program A = new Program();//A是Program类的另外一个对象。
        }
    }

接下来说面向对象的三大特征:封装、继承和多态

封装:

C#中可以使用类来达到数据封装的效果,这样就可以把数据与方法封装成单一元素,以便于通过方法存取数据。除此之外还可以控制数据的存取方法。

设计类时,不希望那个直接存取类中的数据,而是希望通过方法存取数据,这样就可以达到封装的目地,方便维护升级,也可以在操作数据时多一层判断。

另外,封装还可以解决数据存取权限问题,我们并不希望我们的数据会被别人随便的修改,对于一些敏感数据,如果不加以限制让别人随便访问和修改,那么后果是很严重的。同样我们可以对外开放接口开放权限哪些可以访问那些不可以访问。封装的目地是增强安全性和简化编程。

class Myclass
    {
        private int x = 0;

        public int X
        {
            get { return x; }
            set { x = value; }
        }
        private int z = 0;

        public int Z
        {
            get { return z; }
            set { z = value; }
        }

        public int Add()
        {
            return x + z;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Myclass myadd = new Myclass();
            myadd.X = 1;
            myadd.Z = 5;
            Console.Write(myadd.Add());
        }
    }

类的继承
继承是面向对象编程最重要的特性之一。任何类都可以从另外一个类继承,这就是说,这个类拥有它继承类的所有成员。被继承的类叫做父类或基类,继承类的类叫做子类或者派生类,但是C#中只支持单继承。

继承一个类的时候,类成员的可访问性是一个重要的问题,子类不能访问父类的私有成员,但是可以访问父类的公共成员,意思就是只要使用public生命的类成员,就可以让一个类成员被基类和子类同时访问,同时也可被外部代码访问。

C#中提供了protect访问修饰符,只有子类能访问protect成员,父类和外部代码都不能访问protect成员。

除了成员的保护级别外,还可以为成员定义其继承行为。父类的成员可以是虚拟的,成员可以有继承它的类重写。子类可以提供成员的其它执行代码,这种执行代码不会删除原来的代码,仍可以在类中访问原来的代码,但外部代码不能访问它们。如果没有提供其他执行方式,外部代码就直接访问父类中成员的执行代码(绕口,自行理解。)

另外,基类还可以定义为抽象类。抽象类不可以直接实例化,要使用抽象类就必须继承这个类,然后再实例化。

class Myclass1
    {
        private int x = 0;

        public int X
        {
            get { return x; }
            set { x = value; }
        }
        private int y = 0;

        public int Y
        {
            get { return y; }
            set { y = value; }
        }

        public int Add()
        {
            return x + y;
        }
    }
    class Myclass2:Myclass1//继承中间用冒号
    {
        private int z = 0;

        public int Z
        {
            get { return z; }
            set { z = value; }
        }
        public int Add2()
        {
            return X + Y + Z;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Myclass1 myclass1 = new Myclass1();
            Myclass2 myclass2 = new Myclass2();
            myclass1.X = 1;
            myclass1.Y = 2;
            myclass2.X = 1;
            myclass2.Y = 2;
            myclass2.Z = 3;
            Console.Write(myclass1.Add());
            Console.Write(myclass2.Add2());
        }
    }

类的多态
多态使子类的实例化可以直接赋予基类的变量(这里不需要进行强制类型转换),然后直接就可以通过这个变量调用子类的方法。

在派生于同一个类的不同对象上执行任务时,多态是一种极为有效的技巧,,使用代码最少。可以把一组对象放到一个数组中然后调用他们的方法,在这种情况下多态的作用就体现出来,这些对象不必是相同类型的对象。当然如果它们继承自某个类,可以把这些子类都放到一个数组中。如果这些对象都有同名方法,就可以调用每个对象的同名方法。

class Myclass1
    {
        private int x = 0;

        public int X
        {
            get { return x; }
            set { x = value; }
        }
        private int y = 0;

        public int Y
        {
            get { return y; }
            set { y = value; }
        }

        public virtual int Add() //定义一个virtual类型的方法以便于在子类中重写该方法求和
        {
            return x + y;
        }
    }
    class Myclass2:Myclass1
    {
        public override int Add()
        {
            int x = 1;
            int y = 2;
            return x + y;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Myclass2 myclass2 = new Myclass2();//实例化Myclass2的对象
            Myclass1 myclass1 = (Myclass1)myclass2;//使用子类Myclass2的对象实例化基类Myclass1的对象
            myclass1.X = 1;
            myclass2.Y = 2;
            Console.Write(myclass1.Add());//调用父类中的方法
            Console.Write(myclass2.Add());//调用子类中的方法
        }
    }

注意:

1、virtual修饰符不能同时与private、static、abstract或者override修饰符同时使用。
2、override修饰符不能与new、static或者virtual修饰符同时使用,并且重写方法只能用于重写父类中的虚方法。

3、C#中,继承、虚方法和重写方法组合在一起才能实现多态性。

参考资料:C#入门到精通

原文地址:https://www.cnblogs.com/dawenhao/p/4909456.html