【问题标题】:What is the difference between Abstraction and Polymorphism抽象和多态有什么区别
【发布时间】:2010-09-26 21:45:15
【问题描述】:

我似乎不太了解两个 OOP 概念。你能解释一下什么是抽象多态,最好用真实的例子和代码?

谢谢。

【问题讨论】:

  • 我觉得这听起来不像是功课,我会说他/她只是很难理解。
  • 这不是功课,但就在我和我的团队讨论时,这些概念变得有点相似。这就是为什么他们让我感到困惑。抽象是指事物没有具体的细节,多态是指不同对象的方法相同,但做不同的任务。我说的对吗?

标签: oop polymorphism abstraction


【解决方案1】:

在面向对象的上下文中,关于抽象的实际含义的混淆是可以理解的:它对继承、封装甚至多态的概念几乎没有增加什么。如果掌握了这三个概念,一旦“抽象”自然嵌入其中(尤其是继承),就无需过多关注。

首先,请注意术语“抽象”具有多种含义,并且它的陈述是正确的,例如,封装需要抽象:当您使用访问修饰符来保护一个对象的属性时类在暴露处理它们的方法(这就是封装)的同时,类的用户不再需要担心如何自己处理它们。所以,从某种意义上说,当你设计一个类时,你抽象通过适当地封装方法和属性——类的用户需要做的一切就是通过调用正确的方法来使用它,这是一种形式的抽象。

此外,如果你想清楚的话,多态性也是一种抽象形式:你的代码调用了某个类提供的方法,而在实际的类类型为确定(在运行时)。所以,说多态行为是一种抽象是正确的。

然而,当作为一个独立的术语来描述 OOP 的特性时,抽象必须被理解为以合适的类层次结构的形式对所讨论的系统进行适当的表示。因此,抽象是设计者心理过程的结果,最终为程序中要使用的类进行适当的设计。引用(优秀的!)帖子that can be found at the javarevisited blog

... 抽象在设计层面隐藏细节,而封装 在实现级别隐藏细节。

虽然上述陈述是正确的,但我发现“隐藏细节”部分有误 - 我会将其改写为

抽象关注设计细节,决定类层次结构应该是什么样子,封装隐藏细节 实施

为了公平对待作者,这个想法在他的文章中得到了很好的体现。在Head First Object-Oriented Analysis and Design这样的好书中也可以看到具有这种含义的“抽象”一词,我从那里引用了一个声明:

每当您在两个或多个地方发现共同行为时,请查看 将该行为抽象为一个类,然后在 常用类

请注意此处抽象的用法:“希望将该行为抽象为一个类”。现在,如果抽象意味着正确地设计一个类层次结构,那么抽象可以定义为通过方便地使用类来表示域,利用继承和封装的概念

在 Java 的特殊情况下,抽象是使用 interfacesabstract classes 实现的,而封装是使用 private, protected and package access modifiers 实现的。

【讨论】:

    【解决方案2】:

    简单来说,抽象是概念性的,而多边形是行为性的。为了在 OOP 中实现抽象,您需要 Poly。

    我可以说面向对象编程中的抽象是一种概念或设计模式,它可以实现更好的隔离、松散耦合,从而实现可测试性、可重用性和可扩展性。为了实现所有,我们需要poly、继承/扩展等。

    【讨论】:

    • 或者,设计提供多态性以使抽象成为可能。
    【解决方案3】:

    抽象和多态在本质上相似,但目的不同。

    例如

    驾驶执照:您将获得一张执照,上面注明您可以驾驶的车辆类别。许可证提到了当局允许的车辆类别,但没有定义或提及您应该驾驶的特定汽车或品牌。这是抽象。

    这里License是一个抽象类,它的方法,允许的车辆是它的抽象方法

    现在,在这里,多态性是当局将个人许可证分配给不同的人的不同方式,根据不同的要求,有些是为轻型车辆颁发的,有些是为重型车辆颁发的,有些是为商用车颁发的。在这里,License 是一个基类其他种类的许可证是它的子类,也遵循 is-a 关系。商业许可证就是许可证。

    因此,抽象是一种通用准则,它赋予后续类实现独立性,而多态是差异化方法,它覆盖父类设置的方法/规则。

    【讨论】:

      【解决方案4】:

      P.S:最近开始学习java答案是基于我的观察,如果我错了请纠正我。

      抽象和多态基本上在编程中做几乎相同的工作。

      我们以汽车为例..

      无论是福特小型货车、法拉利异国情调、路虎 SUV 还是宝马轿车,它们都遵循汽车的基本设计,即发动机、方向盘、变速箱、车灯、 指标和列表继续。使它们与众不同的是它们的具体实现,例如法拉利可能拥有比小型货车更强大的发动机,SUV 可能具有不同的齿轮箱 因此,汽车(此处为超类)已由子类(轿车、SUV、小型货车、异国情调)实现 这就是多态性,一种通过添加其他规范来继承或实现的基本思想。以各种形式(子类)实现的 4 轮车辆(超类)

      现在,抽象,顾名思义就是隐藏细节,让用户看到他需要的东西..

      让我们再次以汽车为例..您使用齿轮,但您并不确切知道齿轮的工作原理和改变速度等等..

      现在开始编码部分。

      抽象类是不完整的类,顾名思义,抽象类需要有一个不完整的方法,该方法需要由继承超类的子类完成,如果它们不完成抽象方法,它们将保留也不完整。

      abstract class car {
        abstract void gear();
      }
      
      class sedan extends car {
       public void gear()
       {
        //complete the method
       }
      }
      

      你也不能创建抽象类的对象,因为类不完整。然而,这些抽象类可以具有静态方法、参数、具体方法,但要使其成为抽象类,它们需要一个抽象方法。因此,一个基本的抽象超类在完成它的其他子类中实现 通过查看方法声明,我们可以估计该方法到底在做什么,它将返回什么。但我们不知道抽象方法将如何实现。

      通过使用抽象类或接口,我们可以在Java中实现抽象。 众所周知,抽象类、接口包含抽象方法

      我们只能估计它们将如何工作。一旦我们在实现相应抽象类或接口的类中提供了方法实现,我们就会知道它们是如何工作的。

      因此,抽象基本上有助于多态性。

      【讨论】:

        【解决方案5】:

        这两个是面向对象范式最重要的特征之一。

        抽象。

        面向对象将软件建模为真实世界的对象。但是,对 Customer 可能拥有的所有属性或 Employee 拥有的所有属性进行建模太难(而且没用)。

        通过仅列出对象的有趣属性,OO 可以有效地将该对象用于特定域。这就是抽象。

        例如,人力资源系统中的员工可能具有与在线书店非常不同的属性。我们把细节抽象出来做有用。

        多态性。

        在保持相同界面的同时,对象的行为可能会因“类型”而异。

        这是什么意思?

        例如,在线商店系统可能有两个 Employee 子类

        A) 内部员工。

        B) 承包商

        以及一种计算内部购买折扣的方法

        内部员工的折扣计算为:10% + 公司每个工作年的 2% + 每个.. mmhh 孩子的 2%

        承包商的折扣是 10%

        以下代码计算支付金额:

         public Amount getAmountToPay( Product product, Employee internalCustomer ) { 
              Amount amount = product.getPrice();
              amount.applyDiscount( internalCustomer.getDiscount() );
              return amount;
         }
        

        对于两种不同的 Employee 会产生不同的结果

        class Employee { 
            public int getDiscount();
        }
        
        
        class InternalEmployee extends Employee { 
             public int getDiscount() { 
                return 10 + 2 * getWorkedYears() + 2 * getNumberOfChilds();
             }
         }
        
         class Contractor extends Employee { 
              public int getDiscount() { 
                  return 10;
             }
         }
        

        这就是多态性的作用。而不是像

         Amount amount = product.getPrice();
        
         if( employee.isContractor() ) { 
              amount.applyDiscount( 10 );
         } else if( employee.isSomthingElse() ) {
              amount.applyDiscount( 10 * 2 * getYrs() + 2 * getChilds() );
         } else if ( employee.contidions, condigions, conditions ) {
              amount.applyDiscount( getSomeStrageRuleHere() );
         }
        

        我们让运行时选择计算哪一个。就像程序的行为因类型而异:

              Amount amount = product.getPrice();
              amount.applyDiscount( internalCustomer.getDiscount() );
              return amount;
        

        顺便说一下,在这个例子中,“金额”是一个现实生活概念的抽象,也可以表示为双精度或整数,但也许我们里面有一些有趣的方法,如果设置在它的自己的班级。

        我希望这会有所帮助。

        【讨论】:

        • 很好的解释!
        【解决方案6】:

        简短回答:抽象是概念,多态是行为

        【讨论】:

          【解决方案7】:

          这两个术语在面向对象编程中都被大量使用,但它们并不仅限于该上下文。

          抽象是对其他事物的概括;视野更上一层楼。例如,层次结构可以看作是对公司组织结构的抽象。通常,它用于底层事物(例如它们的基本类型)的上下文中。抽象的目的是编写更少的本质上更通用的代码,以便您可以运行它来解决更大的问题集。例如,电子表格是一种抽象,它允许特定类型的信息存储。 More?

          多态性也是一种概括,但它发生在运行时上下文中。如果有某种方法可以在它们彼此无法区分的情况下访问它们,那么一堆不同的对象类型是多态的。也就是说,所有对象的外观和感觉都相同,即使它们不同。这样做的目的是显着减少代码;您可以编写一个通用的解决方案来避免为每种不同类型编写所有不同的排列。如果你写一个图形库,你宁愿只写一些抽象代码来处理“形状”,然后必须为每种不同的类型编写代码,比如圆形、正方形等。

          这两个术语都以代码中的属性为中心,使程序员能够事半功倍。更少的代码有更少的错误,更稳定,更容易维护。另一种方法是使用“蛮力”来破解数百万行非常具体(并且非常脆弱)的代码。更多代码更难修复,更难保持最新。

          保罗。

          【讨论】:

            【解决方案8】:

            抽象和多态性是重要的概念,绝不仅限于 OO。更令人困惑的是,“抽象”这个词有多种使用方式。下面是一份快速备忘单,其中包含一个示例:

            • 数据抽象表示信息隐藏。通常隐藏的是数据结构的表示。示例:我实现了集合,但我没有告诉您集合是表示为列表、平衡二叉树还是不平衡二叉树。做得对,我可以在不破坏您的代码的情况下更改表示形式

            • 多态表示与不同类型重用。因此,在我的设置示例中,您可以使用相同的代码创建社会安全号码集、全名集或果蝠集。

            显然你可以定义一个既是抽象类又是多态的类。

            多态更加令人困惑,因为有两种方法可以实现多态。在 parametric polymorphism 中,您可以重用具有 any 类型或任何满足某些约束的类型的值的集合。 最明显的例子C++模板;如果你写

            class Set <T> { ... }
            

            那么T就是集合中包含的对象的类型(&lt;T&gt;表示一个所谓的“类型参数”,这就是它的parametric多态性)。 p>

            子类型多态性中,您只能对类型是特定类型的子类型的对象重用集合。例如,您可能只能创建提供小于或等于方法的对象集。在像 Smalltalk 或 Ruby 这样真正的面向对象语言中,它们提供所谓的duck typing(我们头脑敏锐的理论家有时称之为行为子类型),方法已经足够好了。在像 Java 或 C++ 这样将子类型化与继承混为一谈的语言中,您对多态性的使用可能仅限于特定类的子类。 (Java 通过在类上使用一种子类型而在接口上使用另一种子类型,进一步混淆了这个问题。)

            最后,像我这样的老屁们谈论过程抽象,这只是意味着能够将一堆经常一起使用的语句放入一个过程或方法中,然后你可以重用.这可能与您的问题无关。

            那么,你对困惑感觉更好吗?

            【讨论】:

            • 那么,数据抽象和ad-hoc多态有什么区别?
            【解决方案9】:

            抽象

            想象一个分数类:

            class fraction:
                int denominator
                int numerator
            

            现在有两个对象:

            fraction(obj1): denominator=-1 numerator=-1
            fraction(obj2): denominator=1  numerator=1
            

            两个对象的值都是 1:(1/1) == (-1)/(-1)。你不会期望他们的行为与外界有任何不同。那是抽象。您将对象保存的数据抽象为逻辑视图,即使在幕后,还有其他事情。从理论上讲,您有一个等价关系,具有不同的等价组:

            [1]=(1, 1), (-1, -1), (5, 5), ...
            [2]=(2, 4), (-2, -4), ...
            ...
            

            还有一个抽象函数,将内部细节抽象到外部:

            f((1, 1)) = [1]
            f((-1, -1)) = [1]
            

            它将具体值映射到对象的抽象值。例如,您可以通过编写一个构造函数映射 (-1, -1) 到 (1, 1) 并为您的类编写一个 equals 函数来做到这一点。

            多态性

            想象一支笔和两个派生类:

            class pen:
                void draw(int x, int y)
            
            class pen_thin extends pen:
                void draw(int x, int y) { color(x, y) = green; }
            
            class pen_thick extends pen:
                void draw(int x, int y) { color(x, y) = green; 
                                          color(x, y+1) = green; }
            and two objects:
                pen_thin(p1)
                pen_thick(p2)
            

            两支笔都可以画画。您的一般“笔”无法自行绘制。它只是 pen_thin、pen_thick 和许多其他笔的接口。你说:obj1.draw(1, 0); obj1 是粗笔还是细笔对于您作为用户来说并不重要,对于编译时的编译器也不重要。该调用具有多态性。这是动态多态性(发生在运行时),这就是人们通常的意思。 静态多态发生在编译时:

            class colorizer:
                void colorize(shirt s)
                void colorize(pants p)
            

            这就是所谓的重载。你打电话给obj.colorize(something)。如果你用衬衫引用来调用它,它会调用衬衫的版本。如果你用裤子引用来调用它,它将调用裤子版本。此处所做的选择是在编译时

            【讨论】:

              【解决方案10】:

              抽象是指在不包括背景细节或解释的情况下表示基本特征的行为。类使用抽象的概念,被定义为抽象属性的列表。

              软件抽象的一个例子是Java 的Object.equals(Object o) 方法。您知道它将将此对象与作为参数传入的对象进行比较,但您不知道,也不需要知道它的具体实现方式(除非您是该类的实现者)。

              多态性意味着能够采用一种以上的形式。一个方法在不同的实例中可能有不同的行为。行为取决于操作中使用的数据类型。

              多态性的经典示例之一使用植根于 Animal 类的继承树。所有 Animal 都有一个 makeNoise() 方法,但是 Dog 类和 Cat 类实现它的方式不同。这允许您使用 Animal 引用类型来引用任何 Dog's 和 Cat's。

              Animal a = new Dog();
              Animal b = new Cat();
              

              现在您可以在任一 Animal 实例上调用 makeNoise() 并知道它会发出适当的噪音。如果您有一个动物集合,并且您在运行时不知道每个动物到底是什么类型,这将特别有用。

              【讨论】:

                【解决方案11】:

                很简单。

                1. 抽象就是抽象。 “学生”类是对真实学生的抽象。

                2. 多态是当一个类代表另一个类时,用户不会注意到。当类实现相同的接口或一个类从另一个类派生时,可能会发生这种情况。 “HighSchoolStudent”类派生自“Student”类。当“教师”类在对象上调用#attendance 方法时,它可能不知道该对象是“学生”类还是“HighSchoolStudent”类。

                【讨论】:

                  猜你喜欢
                  • 2011-01-24
                  • 2015-09-26
                  • 2010-10-10
                  • 2013-10-17
                  • 2014-09-21
                  • 2011-01-18
                  • 1970-01-01
                  • 2010-12-27
                  • 1970-01-01
                  相关资源
                  最近更新 更多