zoukankan      html  css  js  c++  java
  • 潜水在OOP(第一天):多态和继承(早期绑定/编译时多态)

    介绍 我写了很多关于MVC、实体框架、存储库模式等高级主题的文章,我的优先级始终是将主题作为一个整体来讨论,这样读者就不必在其他地方寻找缺失的链接。本文将涵盖初学者/初学者开发人员可能寻找的几乎每一个OOP概念,而不仅仅是初学者,本文的目的是帮助有经验的专业人员,他们可能需要温习他们的概念或准备面试。 我将以一种简单、直接的方式介绍这些主题,在需要的地方提供代码片段作为示例。在阅读材料中,我们将使用c#作为编程语言。 我们会遇到一些棘手的问题,不会去寻求足够的理论。理论上可以参考MSDN。 潜水在OOP(第一天):多态和继承(早期绑定/编译时多态)潜水在OOP(第二天):多态和继承(继承)潜水OOP(第三天):多态和继承(动态绑定/运行时多态)潜水在OOP(第四天):多态和继承(关于Abstarct类在c#中)潜水在OOP(第五天):都是用c#访问修饰符(公共/私人/保护/内部/密封/常量/只读的字段)潜水OOP(6天):理解枚举在c#中(一个实际的方法)深入OOP(第七天):用c#属性(一个实际的方法)深入OOP(8天):用c#索引器(一个实际的方法)潜水印锑OOP(9天):了解c#事件(Insight)学习c#(第十天):代表在c#中(一个实际的方法)学习c#(11天):c#事件(一个实际的方法) 的必备条件 由于这是本系列的第一部分,我的读者应该具备c#的基本知识,并且应该了解OOP的概念和术语。 OOP 1. 什么是OOP? OOP的优点是什么? OOP代表“面向对象编程”。记住,它是OOP而不是OOPS, ' S '可以代表系统,概要,结构等。它是一种完全基于对象的编程方法,而不是像过程语言那样仅仅基于函数和过程。它就像围绕对象而不是“动作”和数据而不是逻辑组织的编程语言模型。OOP语言中的“对象”指的是类的特定类型或“实例”。每个对象都有一个与类中的其他对象完全相似的结构,但是可以有单独的属性/值。对象也可以调用特定于该对象的方法 OOP使开发人员更容易构造和组织软件程序。单独的对象可以被修改而不影响程序的其他方面,因此更新和更改用面向对象语言编写的程序也更容易。由于这些年来软件程序的性质越来越大,OOP使得开发这些大型程序更加易于管理和可读。 2. 什么是OOP概念? 下面是对OOP概念的简要解释,我们将详细讨论这些主题。 数据抽象:数据抽象概念的内部和多余的细节的实现逻辑隐藏在最终用户(使用程序)。用户可以使用任何数据和方法的类不知道这是如何创建或什么是其背后的复杂性。的一个真实世界的例子,当我们驾驶一辆自行车和改变齿轮内部不需要关心如何工作,如何把杆或链是集继承:继承是OOP的最受欢迎的概念。这提供了一个开发人员的优势被称为代码的可重用性。假设一个类被编写为具有特定逻辑的函数,然后我们可以将这个类派生到我们新创建的类中,我们不必为派生类函数重新编写逻辑,我们可以原样使用它们。数据封装:将类的成员数据和成员函数封装在单个单元中称为封装。成员函数的可见性,数据成员是通过类中使用的访问修饰符来设置的。多态:多就是多,射态就是变化的或可改变的。这些概念以对象的许多行为的形式引入。消息通信:消息通信是指对象将调用传递给类的方法以执行。 好了,我们已经讲了很多理论,现在是行动的时候了。我希望会很有趣。我们将在接下来的系列中讨论这些主题, 3.多态: 在本文中,我们将详细介绍编译类型多态性的几乎所有场景,params关键字的使用,以及编写代码时想到的各种可能的组合的案例研究。 方法重载或早期绑定或编译时多态性 注意:每一个代码片段写本文是尝试和测试。 让我们创建一个名为InheritanceAndPolymorphism的简单控制台应用程序,并添加一个名为Overload.c的类并添加三个名为display重载的方法,其参数变化如下: Overload.cs 隐藏,复制Codepublic类重载 { public void display重载(int a){ System.Console。WriteLine(“DisplayOverload”+ a); } public void display重载(string a){ System.Console。WriteLine(“DisplayOverload”+ a); } public void display重载(字符串a, int b){ System.Console。WriteLine(“DisplayOverload”+ a + b); } } 在main方法的Program.cs文件中,添加以下代码, Program.cs 隐藏,复制Codeclass程序 { 静态void Main(string[] args) { new重载(); overload.DisplayOverload (100); 过载。DisplayOverload(“方法重载”); 过载。DisplayOverload(“方法重载",100); Console.ReadKey (); } } 当你运行这个应用程序时,输出是, 输出 DisplayOverload 100 DisplayOverload方法重载 DisplayOverload overloading100方法 类重载包含三个名为display重载的方法,它们仅在由其组成的参数的数据类型上有所不同。在c#中,我们可以使用相同名称的方法,但是它们的参数的数据类型应该不同。c#的这个特性称为方法重载。因此,如果一个方法的行为不同,我们不需要记住大量的方法名,只有为方法提供不同的参数才能单独调用一个方法。 请记住:c#通过参数识别方法,而不仅仅是通过它的名称。 签名表示方法的全名。因此,方法的名称或其签名是原始方法名称加上其单个参数的数量和数据类型。 如果我们使用以下代码运行项目, 隐藏,复制Code

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

    我们肯定会得到编译时错误, 错误:“InheritanceAndPolymorphism类型。重载'已经定义了具有相同参数类型的名为' display重载'的成员 这里我们有两个函数,它们的不同之处在于它们返回的值的数据类型,但是我们在编译时出现了错误,因此,需要记住的另一点是, 请记住:如果方法的名称相同,方法的返回值/参数类型决不是方法签名的一部分。所以这不是多态性。 如果我们使用以下代码运行项目, 隐藏,复制Code

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

    我们再次得到一个编译时错误, 错误:“InheritanceAndPolymorphism类型。重载'已经定义了具有相同参数类型的名为' display重载'的成员 与上面代码中的修改不同,我们现在有两个display重载方法,它们接受一个int(整型)。唯一的区别是有一个方法被标记为静态。这里方法的签名将被视为与修饰符相同,比如static也不被视为方法签名的一部分。 注意:像静态这样的修饰符不被认为是方法签名的一部分。 如果我们按照下面的代码运行程序,考虑到方法签名现在不同了, 隐藏,复制Code

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

    我们再次得到一个编译时错误, 错误:不能定义重载方法' display重载',因为它只在ref和out上不同于其他方法 方法的签名不仅包括参数的数据类型,还包括参数的类型/类型,如ref或out等。方法display重载采用一个具有不同访问修饰符的int,例如out/ref等,每个的签名都是不同的。 注意:方法的签名由它的名称、数字和形式参数的类型组成。函数的返回类型不是签名的一部分。两个方法不能具有相同的签名,而且非成员不能具有与成员相同的名称。 4. 参数在多态性中的作用 一个方法可以由四种不同类型的参数调用。 作为输出参数,使用参数数组按值、按引用传递。 如前所述,参数修饰符从来不是方法签名的一部分。现在让我们关注参数数组。 方法声明意味着在内存中创建一个单独的声明空间。因此,在方法结束时,所创建的任何内容都将丢失。 运行代码, 隐藏,复制Code

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

    导致编译时错误, Error1:参数名“a”是重复的 Error2:一个名为“A”的局部变量不能在这个范围内声明,因为它会给“A”赋予不同的含义,而“A”已经在“父”或“当前”范围内用于表示其他东西 请记住:参数名应该是唯一的。同样,我们不能在同一个函数中同时使用参数名和声明变量名。 在按值传递的情况下,传递的是变量的值,在ref和out情况下,传递的是引用的地址。 当我们运行以下代码时, Overload.cs 隐藏,复制Code

    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 隐藏,复制Code

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

    我们得到, 输出 (Akhil (Akhil 1 (Akhil 2 Akhil3 我们可以任意多次传递相同的ref参数。在显示的方法中,字符串名的值为Akhil。然后,通过将字符串x更改为Akhil1,我们实际上是将字符串名称更改为Akhil1,因为名称是通过引用传递的。变量x和name引用内存中的相同字符串。改变一个也会改变另一个。同样,更改y也会更改name变量,因为它们引用相同的字符串。因此,变量x、y和name引用内存中的相同字符串。 当我们运行以下代码时, Overload.cs 隐藏,复制Code

    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 隐藏,复制Code

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

    我们得到输出, 输出 (Akhil 100 米塔尔100 OOP 100 (Akhil 200 我们经常会遇到这样的情况:我们希望向一个方法传递n个参数。由于c#在传递参数给方法方面非常特殊,如果我们在需要传递字符串的地方传递int,它会立即失效。但是c#提供了一种向方法传递n个参数的机制,我们可以通过params关键字来实现。 请记住:这个params关键字只能应用于方法的最后一个参数。所以n个参数只能在最后。 在方法display重载的情况下,第一个参数必须是一个整数,其余的可以是从0到无限个字符串。 如果我们添加一个方法, 隐藏,复制Code

    private void DisplayOverload(int a, params string[] parameterArray, int b) {  }

    我们得到一个编译时错误, 错误:参数数组必须是形式参数列表中的最后一个参数 这样就证明了params关键字将是方法中的最后一个参数,这已经在最新的一点要记住说明。 Overload.cs 隐藏,复制Code

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

    Program.cs 隐藏,复制Code

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

    当我们运行代码时, 200 100 300 100 100 200 因此, 请记住:c#非常聪明,它能识别倒数第二个参数和参数是否具有相同的数据类型。 第一个整数存储在变量a中,其余的作为数组参数数组的一部分。 隐藏,复制Code

    private void DisplayOverload(int a, params string[][] parameterArray)  {     }
    
    private void DisplayOverload(int a, params string[,] parameterArray)    {    }

    对于上面写的代码,我们再次得到一个编译时错误和一个需要记住的新点, 错误:参数数组必须是一维数组 注意事项:与以上错误相同。 参数的数据类型必须是一维数组。因此[][] 允许,但不允许。我们也不允许将params关键字与ref或out组合在一起。 Overload.cs 隐藏,复制Code

    public class Overload
        {
            public void Display()
            {
                string[] names = {"Akhil", "Ekta", "Arsh"};
                DisplayOverload(3, names);
            }
    
            private void DisplayOverload(int a, params string[] parameterArray)
            {
                foreach (var s in parameterArray)
                    Console.WriteLine(s + " " + a);
            }
    
        }

    Program.cs 隐藏,复制Code

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

    输出 (Akhil 3 Ekta”3 Arsh 3 因此,允许我们传递一个字符串数组而不是单个字符串作为参数。这里,names是一个使用短格式初始化的字符串数组。在内部,当我们调用函数display重载时,c#将字符串数组转换为单个字符串。 Overload.cs 隐藏,复制Code

    public class Overload
        {
            public void Display()
            {
               string [] names = {"Akhil","Arsh"};
               DisplayOverload(2, names, "Ekta");
            }
    
            private void DisplayOverload(int a, params string[] parameterArray)
            {
                foreach (var str in parameterArray)
                    Console.WriteLine(str + " " + a);
            }
    
        }

    Program.cs 隐藏,复制Code

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

    输出 错误:最好的重载方法匹配“继承和多态性。重载”。显示重载(int, params字符串[])'有一些无效的参数 参数2:不能从'string[]'转换为'string' 我们有两个错误。 对于上面提到的代码,c#不允许混合和匹配。我们假设最后一个字符串“Ekta”将被添加到字符串名称数组中,或者将名称转换为单个字符串,然后将字符串“Ekta”添加到其中。完全合乎逻辑的。 在调用函数display重载之前,c#将所有单独的参数累加起来,并将它们转换为params语句的一个大数组。 Overload.cs 隐藏,复制Code

    public class Overload
        {
            public void Display()
            {
                int[] numbers = {10, 20, 30};
                DisplayOverload(40, numbers);
                Console.WriteLine(numbers[1]);
            }
    
            private void DisplayOverload(int a, params int[] parameterArray)
            {
                parameterArray[1] = 1000;
            }
    
        }

    Program.cs 隐藏,复制Code

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

    输出 1000 我们看到,产出的是概念的证明。数组的成员参数数组[1]的初始值为20,在方法display重载中,我们将其更改为1000。所以原始值改变了,这表明数组被赋予了display重载方法,因此得到了证明。 更多文章,请接触实际的方法。 Overload.cs 隐藏,复制Code

    public class Overload
        {
            public void Display()
            {
                int number = 102;
                DisplayOverload(200, 1000, number, 200);
                Console.WriteLine(number);
            }
    
            private void DisplayOverload(int a, params int[] parameterArray)
            {
                parameterArray[1] = 3000;
            }
    
        }

    Program.cs 隐藏,复制Code

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

    输出 102 在上面提到的场景中,c#创建了一个包含1000 102和200的数组。现在我们将数组的第二个成员更改为3000,它与变量数无关。由于display重载不知道数字,所以display重载如何更改int数字的值?因此它保持不变。 Overload.cs 隐藏,复制Code

    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 隐藏,复制Code

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

    输出 parameterArray 这两个整数200 300 parameterArray 现在我们将讨论方法重载。c#是非常有天赋的。它不欣赏params语句,并将其视为继子。当我们只有一个整数调用display重载时,c#只能调用tak的display重载es参数作为参数,它只匹配一个int数组也可以包含一个成员。的乐趣是DisplayOverload现在被称为两个整数。我们这里有一个两难的局面。c#可以调用参数DisplayOverload或DisplayOverload两个整数。正如前面所讨论的,c#将参数作为第二类成员,因此选择DisplayOverload有两个整数。当有两个以上的整数第三方法调用c#无效的选择,只能勉强选择DisplayOverload参数。c#选择的参数作为最后的手段之前萎靡不振的一个错误。 现在有点棘手的例子,但重要的是, Overload.cs 隐藏,复制Code

    public class Overload
        {
            public static void Display(params object[] objectParamArray)
            {
                foreach (object obj in objectParamArray)
                {
                    Console.Write(obj.GetType().FullName + " ");
                }
                Console.WriteLine();
    
            }
        }

    Program.cs 隐藏,复制Code

    class Program
        {
            static void Main(string[] args)
            {
                object[] objArray = { 100, "Akhil", 200.300 };
                object obj = objArray;
                Overload.Display(objArray);
                Overload.Display((object)objArray);
                Overload.Display(obj);
                Overload.Display((object[])obj);
                Console.ReadKey();
    
            }
        }

    输出 系统。Int32系统。字符串System.Double System.Object [] System.Object [] 系统。Int32系统。字符串System.Double 首先我们通过方法显示数组的对象,对象的样子。因为所有来自一个共同的基类的类对象,我们可以这么做。该方法显示一个对象数组objectParamArray。在foreach对象类有一个名为方法返回一个对象的方法,它看起来像类型,这也叫FullName方法返回类型的名称。从三种不同类型显示。在第二个方法调用显示我们铸造objArray对象。由于没有转换可以从将一个对象转换为一个对象数组对象[],所以只有一个元素对象创建[]。第三调用相同的情况下,最后明确投下一个对象数组。 证据的概念, Overload.cs 隐藏,复制Code

    public class Overload
        {
            public static void Display(params object[] objectParamArray)
            {
                Console.WriteLine(objectParamArray.GetType().FullName);
                Console.WriteLine(objectParamArray.Length);
                Console.WriteLine(objectParamArray[0]);
    
            }
        }

    Program.cs 隐藏,复制Code

    class Program
        {
            static void Main(string[] args)
            {
                object[] objArray = { 100, "Akhil", 200.300 };
                Overload.Display((object)objArray);
                Console.ReadKey();
            }
        }

    输出 System.Object [] 1 System.Object [] 5. 结论 在这篇文章中我们的潜水OOP系列我们了解编译时多态,它也被称为早期绑定或方法重载。我们满足大部分场景特定于多态性。我们还学习了强大的参数关键字的使用及其使用多态性。 总之让列表下的所有指向记得又一次, , c#识别方法的参数,而不是只能通过它的名称。方法的返回值、参数类型不方法签名的一部分,如果方法的名称相同。所以这不是多态性。修饰符,如静态不考虑作为方法签名的一部分。包括它的名称、方法的签名形式参数的数量和类型。函数的返回类型不是签名的一部分。两种方法也不能有相同的签名和非会员不能具有相同的名称作为成员。参数名称应该是唯一的。我们也不能有一个名称和一个参数声明变量名相同的函数一样。按值传递,变量的值传递,在裁判的情况下,引用的地址传递。这个参数关键字只能用于该方法的最后一个参数。所以n参数只能在最后。c#非常聪明认识到如果倒数第二参数和参数具有相同的数据类型。参数数组必须一维数组。 在后面的文章中我们将讨论主题以相同的方式。, 我的其他系列文章: MVC: http://www.codeproject.com/Articles/620195/Learning-MVC-Part-Introduction-to-MVC-Architectu RESTful webapi: http://www.codeproject.com/Articles/990492/RESTful-Day-sharp-Enterprise-Level-Application 编码快乐! 本文转载于:http://www.diyabc.com/frontweb/news1983.html

  • 相关阅读:
    初识分布式计算:从MapReduce到Yarn&Fuxi
    日志的艺术(The art of logging)
    关于负载均衡的一切:总结与思考
    打印中文dict list的各种姿势
    不想再被鄙视?那就看进来! 一文搞懂Python2字符编码
    什么是分布式系统,如何学习分布式系统
    再论分布式事务:从理论到实践
    从银行转账失败到分布式事务:总结与思考
    git命令
    IntelliJ idea 中使用Git
  • 原文地址:https://www.cnblogs.com/Dincat/p/13456773.html
Copyright © 2011-2022 走看看