zoukankan      html  css  js  c++  java
  • 深入浅出OOP(一): 多态和继承(早期绑定/编译时多态)

    

    在本系列中,我们以CodeProject上比較火的OOP系列博客为主。进行OOP深入浅出展现。

    不管作为软件设计的高手、或者菜鸟,对于架构设计而言。均须要多次重构、取舍。以有利于整个软件项目的健康构建,有些经验是前辈总结的,我们拿来使用就可以,有些是团队知识沉淀的,总之复用前人好的思想有利于降低返工。当然,在面试的时候,假设能环绕OOP大谈特谈,自然会加分多多的。

    開始阅读本系列博客的预备知识,多态、封装、面向对象编程等。请通过MSDN学习。

    例如以下图的术语,您应该耳熟能详的。本系列文章使用C#作为唯一脚本语言。

    image

    OOP

    1 是什么OOP。以及OOP的优势是什么?

    OOP代表的是面向对象编程(Object-Oriented Programming),它基于对象的总体进行编程,代替了基于过程函数的编程思想。

    详细实现是环绕对象进行数据、函数封装。而不是基于逻辑关系。

    OOP中的对象直达的是一个特定的类型、或者某类型的实例对象、很多其它时候是一个class。每一个class对象的结构基本类似,可是有各自特有的属性和数据值。对象之间可通过对外的接口进行訪问:方法、属性等。

    基于OOP的这些优势。独立的对象能够改动而不会影响到其它对象,这样会比較方便的升级软件降低潜在的bug。软件系统随着时间的推移,会变得越来越大。OOP编程思想有效的提高了系统代码的可读性和管理性。

    image

    2 OOP的概念是什么?

    以下用5个术语来说明OOP的详细概念是什么:

    • 数据抽象(Data Abstraction):数据抽象是对须要操作的物体进行建模的出发点,既对使用对象进行了抽象。隐藏了内部的细节(对使用的终于用户而言)。

      用户能够很方便的使用class的方法、数据。而不用关心数据创建、执行逻辑的背后复杂的过程。

      我们以真实世界为例,当你骑一辆自行车的时候,不用考虑变速齿轮的原理怎样驱动链条、车轮吧。

    • 继承(Inheritance):继承是OOP概念中最流行的一个概念。继承给程序猿提供了可复用代码的优势。

      基类定义好函数逻辑,子类通过继承,可实现直接訪问--就想子类自身的方法一样方便。

    • 数据封装(Data Encapsulation):对class的成员变量、成员函数通过訪问控制符进行包装。则称为数据封装。訪问控制符有public、Protected、Private、Internal 4种类型。

    • 多态(Polymorphism):对象可通过传递不同參数实现同样的动作,这样的行为我们称之为多态。我们以真实世界为例,“开车”这种方法,对不同类型的用户要提供不同的參数实现多态,如Car.Drive(Man), Car.Drive(Woman)等。
    • 消息通信(Message Communication):消息通信意味着通过通过消息进行class函数的调用、执行。

    3 多态(Polymorphism)

    在本节,我们分别用代码片段来阐述各自类型的多态类型:函数重载、早期绑定、编译器的多态。

    先创建一个console 工程,并命名为InheritanceAndPolymorphism。然后加入类Overload.cs,再加入DisplayOverload函数。

    public class Overload
        {
            public void DisplayOverload(int a){
                System.Console.WriteLine("DisplayOverload " + a);
            }
            public void DisplayOverload(string a){
                System.Console.WriteLine("DisplayOverload " + a);
            }
            public void DisplayOverload(string a, int b){
                System.Console.WriteLine("DisplayOverload " + a + b);
            }
        }

    Program.cs加入例如以下代码:

    class Program
        {
            static void Main(string[] args)
            {
                Overload overload = new Overload();
                overload.DisplayOverload(100);
                overload.DisplayOverload("method overloading");
                overload.DisplayOverload("method overloading", 100);
                Console.ReadKey();

    执行程序,结果例如以下:

    DisplayOverload 100
    DisplayOverload method overloading
    DisplayOverload method overloading100

    Overload类中的DisplayOverload提供了3类不同的重载函数:方法名同样,參数类型和个数不同。C#中的这样的方式成为重载。既我们不须要为每类函数定义不同名字的函数,仅须要改变函数參数类型和个数就可以实现,这个也成为函数签名。

    用不同的返回值能够否? 我们试试以下的代码:

    public void DisplayOverload() { }
    public int DisplayOverload(){ }

    肯定的结果是,Visual Studio会给予例如以下的报错信息:

    Error: Type 'InheritanceAndPolymorphism.Overload' already defines a member called 'DisplayOverload' with the same parameter types

    从上面的结果可知:返回值不作为多态函数签名。

    我们再执行例如以下的代码:

    static void DisplayOverload(int a)  {   }
    public void DisplayOverload(int a) {   }
    public void DisplayOverload(string a){  }

    结果依旧是报错:

    Error: Type 'InheritanceAndPolymorphism.Overload' already defines a member called 'DisplayOverload' with the same parameter types

    结论:static的可见函数修饰符不作为重载签名。

    执行以下的代码,试试out、ref可否作为重载签名。

    private void DisplayOverload(int a) {   }
    
    private void DisplayOverload(out int a)
            {
                a = 100;
            }
    
    private void DisplayOverload(ref int a) {   }

    结果是例如以下的报错:

    Error: Cannot define overloaded method 'DisplayOverload' because it differs from another method only on ref and out

    结论:ref、out传递參数修饰符也不能作为重载签名。

    4 多态中Params 參数的作用

    一个函数可包括例如以下4种类型的參数传递:

    • 值传递 (pass by value)
    • 引用传递 (Pass by reference)
    • 作为output參数 (As an output parameter)
    • 使用參数数组 (Using parameter arrays)

    我们执行例如以下代码:

    public void DisplayOverload(int a, string a)  {   }
    
            public void Display(int a)
            {
                string a;
            }

    不出意外。获得例如以下报错信息:

    Error1: The parameter name 'a' is a duplicate

    Error2: A local variable named 'a' cannot be declared in this scope because it would give a different meaning to 'a', which is already used in a 'parent or current' scope to denote something else

    在同样的作用域中,參数名称必须是唯一的。

    在Overload.cs文件里,加入例如以下代码:

    public class Overload
        {
            private string name = "Akhil";
    
            public void Display()
            {
                Display2(ref name, ref name);
                System.Console.WriteLine(name);
            }
    
            private void Display2(ref string x, ref string y)
            {
                System.Console.WriteLine(name);
                x = "Akhil 1";
                System.Console.WriteLine(name);
                y = "Akhil 2";
                System.Console.WriteLine(name);
                name = "Akhil 3";
            }
        }

    在Program.cs中加入例如以下代码:

    class Program
        {
            static void Main(string[] args)
            {
                Overload overload = new Overload();
                overload.Display();
                Console.ReadKey();
            }
        }

    执行结果例如以下:

    Akhil
    Akhil 1
    Akhil 2
    Akhil3

    image

    结论:我们通过ref引用传递了name的内存地址。故改动x、y的值相当于直接改动name的值。故结果执行如上。

    以下这段代码演示了paramskeyword的作用:

    在Overload.cs文件加入例如以下代码:

    public class Overload
        {
            public void Display()
            {
                DisplayOverload(100, "Akhil", "Mittal", "OOP");
                DisplayOverload(200, "Akhil");
                DisplayOverload(300);
            }
    
            private void DisplayOverload(int a, params string[] parameterArray)
            {
                foreach (string str in parameterArray)
                   Console.WriteLine(str + " " + a);
            }
        }

    在Program.cs文件加入例如以下代码:

    class Program
        {
            static void Main(string[] args)
            {
                Overload overload = new Overload();
                overload.Display();
                Console.ReadKey();
            }
        }

    执行结果例如以下:

    Akhil 100
    Mittal 100
    OOP 100
    Akhil 200

    C#提供了params动态參数数组机制,很方便的在执行时动态传递不同数量的同类型參数。

    注:params关键词仅能作为函数的最后一个參数适用。

    我们再试试paramskeyword的函数签名和非paramskeyword函数签名的优先级顺序:

    public class Overload
        {
            public void Display()
            {
                DisplayOverload(200);
                DisplayOverload(200, 300);
                DisplayOverload(200, 300, 500, 600);
            }
    
            private void DisplayOverload(int x, int y)
            {
                Console.WriteLine("The two integers " + x + " " + y);
            }
    
            private void DisplayOverload(params int[] parameterArray)
            {
                Console.WriteLine("parameterArray");
            }
    
        }

    Program.cs文件加入例如以下代码:

    class Program
        {
            static void Main(string[] args)
            {
                Overload overload = new Overload();
                overload.Display();
                Console.ReadKey();
            }
        }

    执行结果例如以下:

    parameterArray
    The two integers 200 300
    parameterArray

    从执行结果看。C#很巧妙的进行非params函数的精准匹配优先,如1个int类型3个int类型。则用params类型匹配;2个int类型,用明白定义的函数进行匹配。

    5 结论

    image

    在本节中。我们进行OOP系列的第一篇。主要说明了编译器的多态,它也称为早期绑定或者方法重载。同一时候,我们也学习C#中威力强大的paramskeyword。并用它来实现多态。

    本文要点归纳例如以下:

    • C#函数重载的签名规则是用參数的类型和数量推断,而不是函数的名字。
    • 函数返回值不作为重载签名。
    • 修饰符不作为签名的一部分,如static
    • 同函数中。多个參数名称要唯一
    • ref、out是引用传递。传递的是參数的内存地址
    • params 作为參数关键词。仅能用于函数的最后一个參数

    原文地址:http://www.codeproject.com/Articles/771455/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Ear

  • 相关阅读:
    HTTP断点续传 规格严格
    Java Shutdown 规格严格
    linux 命令源码 规格严格
    JTable调整列宽 规格严格
    linux 多CPU 规格严格
    Hello can not find git path 规格严格
    Kill 规格严格
    拜拜牛人 规格严格
    Swing 规格严格
    Debugging hangs in JVM (on AIX but methodology applicable to other platforms) 规格严格
  • 原文地址:https://www.cnblogs.com/jhcelue/p/7118553.html
Copyright © 2011-2022 走看看