• C#中可使用类来达到数据封装的效果,这样可以使数据与方法封装成单一元素,以便于通过方法存取数据。除此之外,还可以控制数据的存取方式。 在面向对象编程中,大多数都是以类作为数据封装的基本单位。类将数据和...

    一、封装
    C#中可使用类来达到数据封装的效果,这样可以使数据与方法封装成单一元素,以便于通过方法存取数据。除此之外,还可以控制数据的存取方式。
    在面向对象编程中,大多数都是以类作为数据封装的基本单位。类将数据和操作数据的方法结合成一个单位。设计类时,不希望直接存取类中的数据,而是希望通过方法来存取数据。这样就可以达到封装数据的目的,方便以后的维护升级,也可以在操作数据时多一层判断。
    此外,封装还可以解决数据存取的权限问题,可以使用封装将数据隐藏起来,形成一个封闭的空间,然后可以设置哪些数据只能在这个空间中使用,哪些数据可以在空间外部使用。一个类中包含敏感数据,有些人可以访问,有些人不能访问,如果不对这些数据的访问加以限制,后果将会非常严重。所以要对类的成员使用不同的访问修饰符,从而定义他们的访问级别。

    封装语法:
    Public 数据类型 变量名
    {
    get
    {
    return 变量名
    }
    set
    {
    变量名=value;
    }
    }

    这里写图片描述
    这里写图片描述

    当然了!get和set有快捷键的:光标选择要封装的属性然后右键点击快速操作和重构…(Chrl+.)点击封装字段(并使用属性)

    这里写图片描述

    这里写图片描述


    二、继承
    继承是面向对象最重要的特性之一。任何类都可以从另外一个类继承,这就是说,这个类拥有它继承类的所有成员。在面向对象编程中,被继承的类称为父类或基类。C#中提供了类的继承机制,但只支持单继承,而不支持多继承,即在C#一次只允许继承一个类,不能同时继承多个类。
    承语法:
    Public class 类名:父类名

    如何使用父类里面的成员变量,方法,构造函数?
    关键字:base

    成员变量:
    base.成员变量名
    方法:
    base.方法名

    **一个类只能继承一个父类跟Java不一yangc#中类继承只允许单继承,但是接口继承允许多继承 ,一个子接口可以有多个父接口, 接口可以从零或多个接口中继承.级继承常会引起继承来的类之间的混乱,继承而来的方法往往没有唯一性,所以C#中类的继承只可以是一个样
    但是可以同时现接口!
    这里写图片描述
    ---------三、多态
    多态性意味着有多重形式。
    在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。
    多态性可以是静态的或动态的。
    在静态多态性中,函数的响应是在编译时发生的。
    在动态多态性中,函数的响应是在运行时发生的。

    1.静态多态性
    在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。
    分别为:
    1.1方法重载:
    可以在同一个范围内对相同的方法名有多个定义。
    方法的定义必须彼此不同,可以是参数列表中的参数类型不 同,也可以是参数个数不同。
    不能重载只有返回类型不同的方法声明。

    1.2运算符重载

    2.动态多态性
    当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。
    2.1:虚方法是使用关键字 virtual 声明的。
    2.2:虚方法可以在不同的继承类中有不同的实现。
    2.3:对虚方法的调用是在运行时发生的。
    2.4:动态多态性是通过抽象类和虚方法实现的。

    定义虚方法:
    访问修饰符 virtual 返回的数据类型/void 方法名()
    {
    //执行代码,也可以完全不写
    }
    重写父类的方法(子类中):
    访问修饰符 override 返回的数据类型
    void 方法名()
    {
    //执行代码
    }-

    namespace PolymorphismApplication
    {
       class Printdata
       {
          void print(int i)
          {
             Console.WriteLine("Printing int: {0}", i );
          }
    
          void print(double f)
          {
             Console.WriteLine("Printing float: {0}" , f);
          }
    
          void print(string s)
          {
             Console.WriteLine("Printing string: {0}", s);
          }
          static void Main(string[] args)
          {
             Printdata p = new Printdata();
             // 调用 print 来打印整数
             p.print(5);
             // 调用 print 来打印浮点数
             p.print(500.263);
             // 调用 print 来打印字符串
             p.print("Hello C#");
             Console.ReadKey();
          }
       }
    }//参考资料在QQ群:683782676
    上面代码被编译执行时结果是
    Printing int: 5
    Printing float: 500.263
    Printing string: Hello C#:
    
    
    
    展开全文
  • C# 多态的实现

    2019-07-04 12:30:45
    封装、继承、多态,面向对象的三大特性,前两项理解相对容易,但要理解多态,特别是深入的了解,对于初学者而言可能就会有一定困难了。我一直认为学习OO 的最好方法就是结合实践,封装、继承在实际工作中的应用随处...

      封装、继承、多态,面向对象的三大特性,前两项理解相对容易,但要理解多态,特别是深入的了解,对于初学者而言可能就会有一定困难了。我一直认为学习OO 的最好方法就是结合实践,封装、继承在实际工作中的应用随处可见,但多态呢?也许未必,可能不经意间用到也不会把它跟“多态”这个词对应起来。在此抛砖引 玉,大家讨论,个人能力有限,不足之处还请指正。
       

        之前看到过类似的问题:如果面试时主考官要求你用一句话来描述多态,尽可能的精炼,你会怎么回答?当然答案有很多,每个人的理解和表达不尽相同,但我比较趋向这样描述:通过继承实现的不同对象调用相同的方法,表现出不同的行为,称之为多态。

     

    例1:

    代码
    public class Animal
        {
            public virtual void Eat()
            {
                Console.WriteLine("Animal eat");
            }
        }

        public class Cat : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Cat eat");
            }
        }

        public class Dog : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Dog eat");
            }
        }

        class Tester
        {
            static void Main(string[] args)
            {
                Animal[] animals = new Animal[3];

                animals[0] = new Animal();
                animals[1] = new Cat();
                animals[2] = new Dog();

                for (int i = 0; i < 3; i++)
                {
                    animals[i].Eat();
                }
            }
        }

     

         输出如下:

    Animal eat...

    Cat eat...

    Dog eat...

     

    在上面的例子中,通过继承,使得Animal对象数组中的不同的对象,在调用Eat()方法时,表现出了不同的行为。

    多态的实现看起来很简单,要完全理解及灵活的运用c#的多态机制,也不是一件容易的事,有很多需要注意的地方。

     

    1. new的用法

    先看下面的例子。

    例2

     

    代码
    public class Animal
        {
            public virtual void Eat()
            {
                Console.WriteLine("Animal eat");
            }
        }

        public class Cat : Animal
        {
            public new void Eat()
            {
                Console.WriteLine("Cat eat");
            }
        }

        class Tester
        {
            static void Main(string[] args)
            {
                Animal a = new Animal();
                a.Eat();

                Animal ac = new Cat();
                ac.Eat();

                Cat c = new Cat();
                c.Eat();
            }
        }

     

    运行结果为:

    Animal eat...

    Animal eat...

    Cat eat...

     

    可以看出,当派生类Cat的Eat()方法使用new修饰时,Cat的对象转换为Animal对象后,调用的是Animal类中的Eat()方法。 其实可以理解为,使用new关键字后,使得Cat中的Eat()方法和Animal中的Eat()方法成为毫不相关的两个方法,只是它们的名字碰巧相同而 已。所以, Animal类中的Eat()方法不管用还是不用virtual修饰,也不管访问权限如何,或者是没有,都不会对Cat的Eat()方法产生什么影响(只 是因为使用了new关键字,如果Cat类没用从Animal类继承Eat()方法,编译器会输出警告)。

     

    我想这是设计者有意这么设计的,因为有时候我们就是要达到这种效果。严格的说,不能说通过使用new来实现多态,只能说在某些特定的时候碰巧实现了多态的效果。

     

     

    2.override实现多态

    真正的多态使用override来实现的。回过去看前面的例1,在基类Animal中将方法Eat()用virtual标记为虚拟方法,再在派生类 Cat和Dog中用override对Eat()修饰,进行重写,很简单就实现了多态。需要注意的是,要对一个类中一个方法用override修饰,该类 必须从父类中继承了一个对应的用virtual修饰的虚拟方法,否则编译器将报错。

     

    好像讲得差不多了,还有一个问题,不知道你想没有。就是多层继承中又是怎样实现多态的。比如类A是基类,有一个虚拟方法method() (virtual修饰),类B继承自类A,并对method()进行重写(override修饰),现在类C又继承自类B,是不是可以继续对 method()进行重写,并实现多态呢?看下面的例子。

     

    例3:

     

    代码
    public class Animal
        {
            public virtual void Eat()
            {
                Console.WriteLine("Animal eat");
            }
        }

        public class Dog : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Dog eat");
            }
        }

        public class WolfDog : Dog
        {
            public override void Eat()
            {
                Console.WriteLine("WolfDog eat");
            }
        }

        class Tester
        {
            static void Main(string[] args)
            {
                Animal[] animals = new Animal[3];

                animals[0] = new Animal();
                animals[1] = new Dog();
                animals[2] = new WolfDog();

                for (int i = 0; i < 3; i++)
                {
                    animals[i].Eat();
                }
            }
    }

     

         运行结果为:

    Animal eat...

    Dog eat...

    WolfDog eat... 

    在上面的例子中类Dog继承自类Animal,对方法Eat()进行了重写,类WolfDog又继承自Dog,再一次对Eat()方法进行了重写, 并很好地实现了多态。不管继承了多少层,都可以在子类中对父类中已经重写的方法继续进行重写,即如果父类方法用override修饰,如果子类继承了该方 法,也可以用override修饰,多层继承中的多态就是这样实现的。要想终止这种重写,只需重写方法时用sealed关键字进行修饰即可。

     

     

    3. abstract-override实现多态

    先在我们在来讨论一下用abstract修饰的抽象方法。抽象方法只是对方法进行了定义,而没有实现,如果一个类包含了抽象方法,那么该类也必须用 abstract声明为抽象类,一个抽象类是不能被实例化的。对于类中的抽象方法,可以再其派生类中用override进行重写,如果不重写,其派生类也 要被声明为抽象类。看下面的例子。

    例4:

     

     

    代码
        public abstract class Animal
        {
          public abstract void Eat();
        }

        public class Cat : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Cat eat");
            }
        }

        public class Dog : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Dog eat");
            }
        }

        public class WolfDog : Dog
        {
            public override void Eat()
            {
                Console.WriteLine("Wolfdog eat");
            }
        }

        class Tester
        {
            static void Main(string[] args)
            {
                Animal[] animals = new Animal[3];

                animals[0] = new Cat();
                animals[1] = new Dog();
                animals[2] = new WolfDog();

                for (int i = 0; i < animals.Length; i++)
                {
                    animals[i].Eat();
                }
            }
        }

     

     

    运行结果为:

    Cat eat...

    Dog eat...

    Wolfdog eat...

    从上面可以看出,通过使用abstract-override可以和virtual-override一样地实现多态,包括多层继承也是一样的。不同之处在于,包含虚拟方法的类可以被实例化,而包含抽象方法的类不能被实例化。

    转载于:https://www.cnblogs.com/Eleanore/p/3208668.html

    展开全文
  • 我们知道封装、继承和多态是面向对象方法设计中的三大基本特性,下面将具体讲解这三个特性的具体表现及意义。 一、封装 1、说明  从字面意思上看,封装就是打包的意思,将什么包装起来,专业一点就是信息...

    我们知道封装、继承和多态是面向对象方法设计中的三大基本特性,下面将具体讲解这三个特性的具体表现及意义。

    一、封装

    1、说明

      从字面意思上看,封装就是打包的意思,将什么包装起来,专业一点就是信息的隐藏,将对象的属性和方法打包成一个相对独立的单位,尽可能隐蔽对象的内部细节,对外形成一个边界,若有其他类或方法想访问这个被封装了的类,需要通过接口来实现,即对外有函数作为通道,对内有变量作为原料。

      对象安全性的高低取决于其封装的程度,我们在声明属性方法时,会有public、private、protected、internal等访问修饰符,这些修饰符就定义了访问的级别,从而也就决定了封装的程度。

    		public——公共成员,完全公开,没有访问限制
    		private——私有成员,在类的额内部才可以访问
    		protected——保护成员,该类内部和继承类(子类) 中可以访问
    		internal——当前程序集内可以访问,类的默认访问修饰符
    

    2、为什么要封装

      可以说,在任何程序中,我们无时无刻都在运用封装这一特性,那么我们为甚么这么频繁的使用封装呢?

      当对象被创建时,如果没有被封装,即可以通过对象的引用获取任意成员的属性值,并能够给所有的成员属性任意赋值。这样是非常危险的,第一,对象中的成员属性是对象本身的特有属性,如果很轻易的被其他对象访问并修改,那这些属性存的意义就没有了。第二,对象中的成员方法只有部分是给外部提供的,有些是对象自己使用的方法,如果外部能够随意调用对象内部的所有方法,这个方法存在也就没有意义了。

      举个例子,在”人”的对象中,提供了”走路”的方法,而”走路”的方法又是通过在对象内部调用”迈左腿”和” 迈右腿”两个方法组成。如果用户在对象的外部直接调用” 迈左腿”或” 迈右腿”的方法就没有意义,应该只让用户能调用”走路”的方法。

      有了封装,我们就能够有效的避免外部错误对内部造成的“交叉感染”,使软件错误能够局部化。

    封装好处:

     1、良好的封装能够减少耦合。
    
    2、类内部的结构可以自由修改。
    
    3、可以对成员进行更精确的控制。
    
    4、隐藏信息,实现细节。
    

    二、继承

    1、说明

      继承是父与子的关系,当代码中需要申请多个类或多个方法时,如果这些类或方法有一定相同的属性,为了减少代码的冗余,可以使用继承关系,减少代码量。

      子类或子函数可以继承父类或父函数中的所有属性,父类中含有所有子类的共同特征。在主函数中为子类或子方法赋值时,可以直接调用父类或父方法中的属性。

    ##2、构造函数中的继承
      之前我们有说过构造函数,他其实就是在一定程度上改变了封装对象接口的类型,不仅减少了代码量,而且增加了被访问对象的安全性。那么如果两个类或方法存在继承关系,在其中使用构造函数时,我们需要注意哪些呢?

      由于子类中属性可能比较多,需要利用到有参的构造函数,当子类在实例化时,会调用父类无参的构造函数来得以实现。但是类都可以实例化,父类也不例外,当父类也利用有参构造函数实例化时,就会覆盖了原来的无参的构造函数(类中都会默认有一个无参的构造函数),从而导致子类的实例化无法实现,所以此时可以再在父类中建立一个无参的构造函数来供子类的调用。

      那么如果子类中有参的构造函数与父类中有参的构造函数有相同的参数,能不能直接通过子类有参的构造函数调用父类有参的构造函数来减少代码的输入量呢?答案是肯定的,这是就用到了base,在子类构造函数后面加上“:base(相同的参数类型)

    这里写图片描述
    这里写图片描述
    这里写图片描述

    三、多态

    1、说明

    多态

    通俗来讲:就是对象能够表现多个类型的能力。
    比较全面的说法:就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。我们不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序选择多个运行状态,这就是多态。

    好吧,举个例子:
      我们定义动物这个类,他有“颜色”属性,有“叫”这个方法,但是如果将动物实例化,比如猫,狗,老鼠等,他们都各自有各自的颜色属性值和叫的方法值。这些都需要在运行期间才能决定,这样在运行期间让程序选择多个运行状态,就是多态。

    2、实现形式

    1>接口

      接口是多态的体现形式,用 Interface 来定义,语法如下:

    	 [访问修饰符] interface 接口名
    			{
    				//接口成员定义
    			}
    

    说明:
    接口不能直接实例化
    接口中没有方法体的实现
    类似于抽象基类,继承接口的任何非抽象类型都必须实现接口的所有成员
    接口之间支持多重继承,但是类不能,类只有一个父类

    2>重写

      子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。

      重写时,子类的方法名和父类的方法名重名,但是子类方法名下会出现一条绿线(不影响使用)

    解决绿线方法:
    1、可以在子类方法的修饰符后面加new,隐藏父类方法(无论是否加new都不影响使用)
    2、可以在父类的方法的修饰符后面加virtual(变成虚方法),在子类的方法的修饰符后面加override(使子类重写父类方法,变成实的),在子类的方法中可以直接使用父类方法也可以重新赋值。

    作用:
      如果我们执行一个操作:申请很多类,将这些类放到集合当中,遍历这个集合的时候,把这些类中的方法全部调用出来。
      如果没有重写,我们就需要一个个判断子类父类能不能转换,然后一个个调用方法。如果有了重写,我们只需要判断子类父类能不能转换,然后再最后调用一个方法就可以了,因为名字相同,只要一个方法调用就可以,内容可以重新覆盖。

    3>抽象方法与抽象类

      子类能够继承父类的一些属性方法,但是很多子类对于父类的这个方法可能有很多不同的值,这时就可以不将父类中的这个方法定死,即写一个抽象类,将这个方法变成抽象方法,在子类中调用这个抽象方法并重写,这样就实现了子类继承父类的特有的方法值。

    规则:

    	抽象用abstract来修饰
    	抽象方法没有方法体
    	抽象方法必须在抽象类当中
    	抽象类只能用作基类,无法实例化 
    	抽象类中可以有非抽象成员
    	抽象类的派生类必须实现抽象方法体
    	父类是抽象类,子类继承了这个类,必须把抽象类中的抽象方法重写
    
    展开全文
  • C#多态的理解

    2009-09-08 10:43:00
    一、什么是多态 面向对象程序设计中的另外一个重要概念是多态性。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。可以把一组对象放到一个数组中,然后调用它们的方法,在这种场合下,多态性作用就...

    一、什么是多态

      面向对象程序设计中的另外一个重要概念是多态性。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。可以把一组对象放到一个数组中,然后调用它们的方法,在这种场合下,多态性作用就体现出来了,这些对象不必是相同类型的对象。当然,如果它们都继承自某个类,你可以把这些派生类,都放到一个数组中。如果这些对象都有同名方法,就可以调用每个对象的同名方法。

      同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。多态性通过派生类重载基类中的虚函数型方法来实现。

      在面向对象的系统中,多态性是一个非常重要的概念,它允许客户对一个对象进行操作,由对象来完成一系列的动作,具体实现哪个动作、如何实现由系统负责解释。

      “多态性”一词最早用于生物学,指同一种族的生物体具有相同的特性。在C#中,多态性的定义是:同一操作作用于不同的类的实例,不同的类将进行不同的解释,最后产生不同的执行结果。C#支持两种类型的多态性:

    ● 编译时的多态性

      编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。

    ● 运行时的多态性

      运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C#中,运行时的多态性通过虚成员实现。

      编译时的多态性为我们提供了运行速度快的特点,而运行时的多态性则带来了高度灵活和抽象的特点。

    二、实现多态

      多态性是类为方法(这些方法以相同的名称调用)提供不同实现方式的能力。多态性允许对类的某个方法进行调用而无需考虑该方法所提供的特定实现。例如,可能有名为 Road 的类,它调用另一个类的 Drive 方法。这另一个类 Car 可能是 SportsCar 或 SmallCar,但二者都提供 Drive 方法。虽然 Drive 方法的实现因类的不同而异,但 Road 类仍可以调用它,并且它提供的结果可由 Road 类使用和解释。

      可以用不同的方式实现组件中的多态性:

    ● 接口多态性。

    ● 继承多态性。

    ● 通过抽象类实现的多态性。

      接口多态性

      多个类可实现相同的“接口”,而单个类可以实现一个或多个接口。接口本质上是类需要如何响应的定义。接口描述类需要实现的方法、属性和事件,以及每个成员需要接收和返回的参数类型,但将这些成员的特定实现留给实现类去完成。

      组件编程中的一项强大技术是能够在一个对象上实现多个接口。每个接口由一小部分紧密联系的方法、属性和事件组成。通过实现接口,组件可以为要求该接口的任何其他组件提供功能,而无需考虑其中所包含的特定功能。这使后续组件的版本得以包含不同的功能而不会干扰核心功能。其他开发人员最常使用的组件功能自然是组件类本身的成员。然而,包含大量成员的组件使用起来可能比较困难。可以考虑将组件的某些功能分解出来,作为私下实现的单独接口。

      根据接口来定义功能的另一个好处是,可以通过定义和实现附加接口增量地将功能添加到组件中。优点包括:

      1.简化了设计过程,因为组件开始时可以很小,具有最小功能;之后,组件继续提供最小功能,同时不断插入其他的功能,并通过实际使用那些功能来确定合适的功能。

      2.简化了兼容性的维护,因为组件的新版本可以在添加新接口的同时继续提供现有接口。客户端应用程序的后续版本可以利用这些接口的优点。

      通过继承实现的多态性

      多个类可以从单个基类“继承”。通过继承,类在基类所在的同一实现中接收基类的所有方法、属性和事件。这样,便可根据需要来实现附加成员,而且可以重写基成员以提供不同的实现。请注意,继承类也可以实现接口,这两种技术不是互斥的。

      C# 通过继承提供多态性。对于小规模开发任务而言,这是一个功能强大的机制,但对于大规模系统,通常证明会存在问题。过分强调继承驱动的多态性一般会导致资源大规模地从编码转移到设计,这对于缩短总的开发时间没有任何帮助。

      何时使用继承驱动的多态性呢?使用继承首先是为了向现有基类添加功能。若从经过完全调试的基类框架开始,则程序员的工作效率将大大提高,方法可以增量地添加到基类而不中断版本。当应用程序设计包含多个相关类,而对于某些通用函数,这些相关类必须共享同样的实现时,您也可能希望使用继承。重叠功能可以在基类中实现,应用程序中使用的类可以从该基类中派生。抽象类合并继承和实现的功能,这在需要二者之一的元素时可能很有用。

      通过抽象类实现的多态性

      抽象类同时提供继承和接口的元素。抽象类本身不能实例化,它必须被继承。该类的部分或全部成员可能未实现,该实现由继承类提供。已实现的成员仍可被重写,并且继承类仍可以实现附加接口或其他功能。

      抽象类提供继承和接口实现的功能。抽象类不能示例化,必须在继承类中实现。它可以包含已实现的方法和属性,但也可以包含未实现的过程,这些未实现过程必须在继承类中实现。这使您得以在类的某些方法中提供不变级功能,同时为其他过程保持灵活性选项打开。抽象类的另一个好处是:当要求组件的新版本时,可根据需要将附加方法添加到基类,但接口必须保持不变。

       何时使用抽象类呢?当需要一组相关组件来包含一组具有相同功能的方法,但同时要求在其他方法实现中具有灵活性时,可以使用抽象类。当预料可能出现版本问题时,抽象类也具有价值,因为基类比较灵活并易于被修改。

    展开全文
  • C# 中访问修饰符: Private:只有类本身能存取. Protected:类和派生类可以存取. Internal:只有同一个项目中的类可以存取. Protected Internal:是Protected和Internal的结合. Public:完全存取. C# 访问修饰...

    C# 中访问修饰符:
    Private:只有类本身能存取.
    Protected:类和派生类可以存取.
    Internal:只有同一个项目中的类可以存取.
    Protected Internal:是Protected和Internal的结合.
    Public:完全存取.
    C# 访问修饰符中默认修饰符
    1.在namespace中的类、接口默认是internal类型的,也可以显示的定义为public类型
    2.在一个类里面,属性和方法默认是private的,可以显示的定义为public、private、protected、internal或protected internal等访问类型。
    3.接口中的方法默认为public的访问权限
    一、封装:
      封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。被封装的对象通常被称为抽象数据类型。
    封装的意义:
      封装的意义在于保护或者防止代码(数据)被我们无意中破坏。在面向对象程序设计中数据被看作是一个中心的元素并且和使用它的函数结合的很密切,从而保护它不被其它的函数意外的修改。
      封装提供了一个有效的途径来保护数据不被意外的破坏。相比我们将数据(用域来实现)在程序中定义为公用的(public)我们将它们(fields)定义为私有的(privat)在很多方面会更好。私有的数据可以用两种方式来间接的控制。第一种方法,我们使用传统的存、取方法。第二种方法我们用属性(property)。
      使用属性不仅可以控制存取数据的合法性,同时也提供了“读写”、“只读”、“只写”灵活的操作方法。
    第一种方法 用传统的读、写方法封装
    让我们来看一个例子有一个类Department,为了操纵这个类中的数据(string departname)我们定义了一个读方法和一个写方法。

    //通过这种方法,我们可以保护私有数据不被外部程序所破坏。使用两个不同的方法来写和读数据**
    public class Department 
    { 
    private string departname; ....... 
    // 读方法 
    public string GetDepartname() 
    { 
        return departname; 
    }
     //写方法 
    public void SetDepartname( string a) 
    { 
        departname=a; 
    } 
    } 
    //主函数  我们不能直接访问类Department的实例d中的私有数据(string departname),我们只能通过读和写的方法来访问。
    public static int Main(string[] args)
    { 
        Department d = new Department(); 
        d.SetDepartname("ELECTRONICS"); 
        Console.WriteLine("The Department is :"+d.GetDepartname()); return 0;
     } 

    第二种方法 用属性来实现封装
    属性是c#引入的一种语言成分,只有很少的语言支持属性。通过对属性的读和写来保护类中的域。第一种方法体身也是一种好的方式,但用属性来实现封装会更方便。 现在我们来看一个例子:

    //属性具有两种操作get和set。Get用来返回属性域的值。Set通过value这个变量来给属性域赋值。
    public class Department
    { 
        private string departname;
        public string Departname
    {
        get { return departname; } 
        set { departname=value; }
      } 
      } 
    public class Departmentmain
    { 
        public static int Main(string[] args) 
        { 
            Department d= new Department(); 
            d.departname="Communication"; 
            Console.WriteLine("The Department is :{0}",d.Departname); return 0; 
    }
     } 

    下面的例子是如何来实现一个只读的属性。类ReadDepartment拥有一个Departname属性只实现了get操作。它省略了写操作。这个特别的类拥有一个构造器,用来接受一个字符串变量。类ReadDepartmain中的Main方法创建了一个新的对象d。对像d的实例使用了类ReadDepartment带有一个字符串参数的构造器。因为上面的属性是只读的,所以我们不给给域departname赋值并且我们只侧读取此域中的值。当然属性也可以是只写的(write-only),这只需属性只具有一个get操作

    //属性可以设为只读的(read-only),下面介绍只读属性只具有一个set操作。   
    using system; 
    public class ReadDepartment 
    { 
        private string departname; 
    public ReadDepartment(string avalue) 
        { departname=avalue; } 
    public string Departname 
    {
         get { return departname; } 
     }
      } 
    public class ReadDepartmain 
    { 
    public static int Main(string[] args)
     { 
         ReadDepartment d= new ReadDepartment("COMPUTERSCIENCE");
         Console.WriteLine("The Department is: {0}",d.Departname); return 0; 
     }
      } 

    第三种 封装既可以对类中的字段进行封装 数组 list数据进行封装

    public class Xdagency
     {
            public string Xdtype { get; set; }
            public List<XdDetail> Details { get; set; }  //list 泛型数据
        }
    public class XdDetail
        {
            public int Month { get; set; }
            public int Count{get;set;}
        }
    public class LoanQueryModel
        {
            public int code { get; set; }
            public string codedesription
            { get
                {
                    switch (code)
                    {
                        case 1:
                            return "请求数据成功";
                        default:
                            return "";
                    }
                }
            }
           public Message[] Message { get; set; }  //数组数据的封装
        }
    public class Message
        {
            public string type { get; set; }
            public string money { get; set; }
            public int c_time { get; set; }
            public string use_company { get; set; }
        }

    二.继承:继承主要实现重用代码,节省开发时间
    1.C#中的继承符合下列规则:
    1.继承是可传递的。如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员。Object类作为所有类的基类。
    2.派生类应当是对基类的扩展。派生类可以添加新的成员,但不能除去已经继承的成员的定义。
    3.构造函数和析构函数不能被继承。除此之外的其它成员,不论对它们定义了怎样的访问方式,都能被继承。基类中成员的访问方式只能决定派生类能否访问它们。
    4.派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已继承的成员。但这并不因为这派生类删除了这些成员,只是不能再访问这些成员。
    5.类可以定义虚文法、虚属性以及虚索引指示器,它的派生类能够重载这些成员,从而实现类可以展示出多态性。
    2.关键字
    1.重载:继承中的重载和类内的成员方法的重载是一样的,只要在子类中新建了和父类中同名的但参数列表不同的成员方法就重载了父类的成员方法,但前题是要能继承改成员方法。
    2. 重写:是在子类中重新改写从父类中继承过来的某个方法,用新的方法代替原有的方法,这里要用关键字virtual override。
    3.隐藏:也是在子类中重新改写从父类中继承过来的某个方法,但不父类的方法替换掉,而是隐藏起来,要用关键字new。
    4.base:可以调用父类的成员方法,除了构造函数和析构函数,派生类将隐式的继承了直接基类的所有成员。也可以显示的调用父类的构造函数来构造子类的成员数据。
    5.this :引用类当前的实例,还用于将对象传递到属于其他类的方法 。

    3.下面给出具体的代码说明如何实现的

     class A 
    { 
        public void Fun1(int i) { }     
        public virtual void Fun3() { } 
        } 
     class B : A
      { 
        public void Fun1(string i)   
        {  //对从A类继承过来的方法进行重构     } 
        public new void Fun2() 
        {  //隐藏了从A类继承过来的方法,可以通过类型的转换从而调用被隐藏的方法     } 
        public override void Fun3()     
        { //重写了从A类继承过来的方法,无法在调用这个方法,对于要重写的方法在父类中必须使用virtual 
        } 
    }

    base 关键字

    using System;
    public class Person
    {
        protected string ssn = "444-55-6666";
        protected string name = "John L. Malgraine";
        public virtual void GetInfo()
        {
            Console.WriteLine("Name: {0}", name);
            Console.WriteLine("SSN: {0}", ssn);
        }
    }
    class Employee : Person
    {
        public string id = "ABC567EFG";
        public override void GetInfo()
        {
            base.GetInfo();    //调用父类的GetInfo()方法
            Console.WriteLine("Employee ID: {0}", id);
        }
    }
    class TestClass
    {
        static void Main()
        {
            Employee E = new Employee();
            E.GetInfo();
        }
    }

    base关键字显示如何指定在创建派生类实例时调用的基类构造函数

    using System;
    public class BaseClass
    {
        int num;
        public BaseClass()
        {
            Console.WriteLine("in BaseClass()");
        }
        public BaseClass(int i)
        {
            num = i;
            Console.WriteLine("in BaseClass(int i)");
        }
       public int GetNum()
        {
            return num;
        }
    }
    
    public class DerivedClass : BaseClass
    {
        public DerivedClass() : base() **//调用父类的构造函数**
        {
        }
        public DerivedClass(int i) : base(i) **//调用父类的构造函数**
        {
        }
        static void Main()
        {
            DerivedClass md = new DerivedClass();
            DerivedClass md1 = new DerivedClass(1);
        }
    }
    //输出
    in BaseClass()    in BaseClass(int i)**

    this 关键字

    using System;
    class Employee
    {
        private string name;
        private string alias;
        private decimal salary = 3000.00m;
        public Employee(string name, string alias)
        {   **//引用类当前的实例**
            this.name = name;
            this.alias = alias;
        }
        public void printEmployee()
        {
            Console.WriteLine("Name: {0}\nAlias: {1}", name, alias);
            Console.WriteLine("Taxes: {0:C}", Tax.CalcTax(this)); **//this 将对象传递到属于其他类的方法CalcTax** 
        }
        public decimal Salary
        {
            get { return salary; }
        }
    }
    class Tax
    {
        public static decimal CalcTax(Employee E)
        {
            return 0.08m * E.Salary;
        }
    }
    class MainClass
    {
        static void Main()
        {
            Employee E1 = new Employee("John M. Trainer", "jtrainer");
            E1.printEmployee();
        }
    }

    三 .多态

    多态实现

    展开全文
  • 浅谈C# 多态的魅力(虚方法,抽象,接口实现) 前言:我们都知道面向对象的三大特性:封装,继承,多态封装和继承对于初学者而言比较好理解,但要理解多态,尤其是深入理解,初学者往往存在有很多困惑,...
  • C#多态分析

    2013-12-05 11:23:32
    理解多态首先是:  C#继承(C# 编程指南) 类可以从其他类中继承。这是通过以下方式实现的:在声明类时,在类名称后放置一个冒号,然后在冒号后指定要从中继承的类(即基类)。例如: public ...
  • c# 封装,继承,多态

    2015-07-21 12:59:34
    一、 封装:  封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。被封装的对象通常被称为抽象数据类型。  面向对象程序设计中一般以类作为数据封装的基本单位...
  • 封装,继承,多态 一、封装 C#中可使用类来达到数据封装的效果,这样可以使数据与方法封装成单一元素,以便于通过方法存取数据。除此之外,还可以控制数据的存取方式。 在面向对象编程中,大多数都是以类作为数据...
  • 封装  被定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中"。在面向对象程序设计方法论中,封装是为了防止对实现细节的访问。 抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可视化...
  • C# 封装、继承、多态

    2018-01-26 14:32:48
    1、封装  隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的“读取”和“修改”的访问级别。   一个 访问修饰符 定义了一个类成员的范围和可见性。C# 支持的访问修饰符如下所示: ● ...
  • 浅谈C# 多态的魅力(虚方法,抽象,接口实现) 前言:我们都知道面向对象的三大特性:封装,继承,多态封装和继承对于初学者而言比较好理解,但要理解多态,尤其是深入理解,初学者往往存在有很多困惑,为...
  • 这是在c#中 如果unity则不需要封装可直接定义 ② 对参数的封装,当一个函数包含多个参数时,可以将多个参数定义在一个类中,这样直接调用这个对象就可以调用多个参数(这样的类仅仅为了封装代码,不是现实物体的...
  • 目录 1.封装 2.继承 3.多态 1.静态多态性 1.函数重载 ...1.封装 ...封装被定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中"。在面向对象程序设计方法论中,封装是为了防止对实现细节的访问。...C# 封装根...
  • C#多态之自动属性

    2019-01-27 12:59:18
    一、C#属性 1.常规属性 先定义一个私有的字段,然后在为这个私有字段封装一个公开的属性,在属性中实现 get 和 set 两个方法,这种方式叫做常规属性。当我们使用常规属性的时候,可以在 get 和 set 方法中,编写...
  • 封装将方法细节隐藏,只留名字。Public:所有对象都可以访问; Private:对象本身在对象内部可以访问; Protected:只有该类对象及其子类对象可以访问 Internal:同一个程序集的对象可以访问; Protected ...
1 2 3 4 5 ... 20
收藏数 16,682
精华内容 6,672