抽象和多态之间有什么区别

时间:2008-12-15 01:37:44

标签: oop polymorphism abstraction

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

谢谢。

11 个答案:

答案 0 :(得分:26)

抽象

想象一下分数类:

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)。如果你用衬衫参考来称呼它,它会打电话给衬衫的版本。如果你用裤子参考调用它,它将调用裤子版本。这里做的选择是在编译时

答案 1 :(得分:13)

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

抽象。

面向对象将软件建模为真实世界对象。但是,对客户可能具有的所有属性或员工拥有的所有属性进行建模将太难(并且无用)。

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

例如,HR系统中的员工可能与Online BookStore具有非常不同的属性。我们抽象细节使得有用。

多态性。

根据“类型”,对象的行为可能会有所不同,同时保持相同的界面。

这意味着什么?

例如,在线商店系统可能有两个子类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;
 }

会为两种不同类型的员工产生不同的结果

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;

顺便说一下,在这个例子中,“Amount”是现实生活概念的抽象,也可以表示为double或Integer,但也许我们内部的interestion方法如果设置在其中会更好自己的班级。

我希望这会有所帮助。

答案 2 :(得分:11)

抽象和多态性是关键概念,绝不仅限于OO。更令人困惑的是,“抽象”这个词被多种方式使用。这是一个快速备忘单,有一个例子:

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

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

显然,您可以定义一个既抽象又具有多态性的类。

多态性进一步令人困惑,因为有两种实现多态的方法。在参数多态中,您可以重复使用任何类型的值,或者可能满足某些约束的任何类型。 最明显的例子 C ++模板;如果你写

class Set <T> { ... }

然后T是集合中包含的对象类型(符号<T>表示所谓的“类型参数”,这使得它成为参数多态)。

子类型多态性中,您只能将集合重用于类型为特定类型的子类型的对象。例如,您可能只能创建提供小于或等于方法的对象的集合。在一个真正的面向对象的语言,如Smalltalk或Ruby,提供所谓的鸭子打字(我们尖头理论家有时称之为行为子类型),存在方法很好。在像Java或C ++这样的语言中,将子类型与继承混合,您对多态的使用可能仅限于特定类的子类。 (Java通过在类上使用一种形式的子类型而在接口上使用另一种形式来进一步混淆问题。)

最后,像我这样的老屁谈论程序抽象,这只是意味着能够将一堆经常一起使用的语句放到一个程序或方法中然后重用。这可能与你的问题没有密切关系。

那么,你是否感到困惑?

答案 3 :(得分:6)

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

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

多态性是指能够采用多种形式。方法在不同的实例中可能具有不同的行为。行为取决于操作中使用的数据类型。

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

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

现在,您可以在任一Animal实例上调用makeNoise(),并知道它会产生适当的噪音。如果你有一个动物集合,这个特别有用,你在运行时并不确切知道每个动物的真实类型。

答案 4 :(得分:3)

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

抽象是其他东西的概括;透视度提高一步。例如,层次结构可以被视为对公司组织结构的抽象。通常,它用于下面的内容(例如它们的基本类型)。抽象的要点是编写更少的代码,这些代码本质上更通用,因此您可以运行它来处理更多的问题。例如,电子表格是一种抽象,允许特定类型的信息存储。 More?

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

这些都是以代码中的属性为中心的术语,这些术语将使程序员能够用更少的资源做更多事情。更少的代码具有更少的错误,更稳定并且更易于维护。另一种方法是使用“强力”来捣毁数百万和数百万行非常具体(且非常脆弱)的代码。更多代码更难以修复,并且更难以保持最新。

保罗。

答案 5 :(得分:3)

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

答案 6 :(得分:2)

抽象和多态性在性质上是相似的,具有不同的目的。

对于前。

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

此处许可抽象类,其方法允许的车辆抽象方法。< / p>

现在,在这里,多态性是不同的方式,个人许可被分配给不同的人,有些是针对轻型车辆发行的,有些是针对重型车辆,有些是针对商用车辆,根据不同的要求。在这里,许可证是基类其他类型的许可证是其子类,同时遵守 is-a relationship 。商业许可证是许可证。

因此,Abstraction是一个通用指南,它将实现的独立性赋予了跟随者类,而Polymorphism是一种差异方法,它覆盖了父类设置的方法/规则。

答案 7 :(得分:0)

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

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

让我们以汽车为例..

无论是福特迷你面包车,法拉利异国情调车,路虎SUV车还是宝马车,它们都遵循汽车的基本设计,即发动机,方向盘,齿轮箱,灯,指标和清单还在继续。让他们与众不同的是他们的具体实施,例如法拉利可能拥有比迷你面包车更强大的引擎,SUV可能有不同的齿轮箱 因此,一辆汽车(超类在这里)已经由子类(轿车,SUV,迷你面包车,异国情调)实施 这是多态,这是通过添加其他规范继承或实现的基本思想。以各种形式(子类)实施的四轮车辆(超级车辆)

现在,抽象,根据定义,它意味着隐藏细节并让用户看到他所需要的东西..

让我们再试一下汽车的例子..你使用的是齿轮,但你并不确切知道齿轮的工作原理和改变速度的机制......

现在编写Part。

抽象类是不完整的类,并且一个类是抽象的,因为名称表明它们需要一个不完整的方法,需要由继承超类的子类完成,如果它们没有完成它们将保留的抽象方法不完整。

abstract class car {
  abstract void gear();
}

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

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

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

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

HENCE,摘要基本上有助于多态性。

答案 8 :(得分:0)

对于面向对象的上下文中抽象的实际含义的困惑是可以理解的:它几乎没有增加(如果有的话)继承,封装甚至多态性的概念。如果您掌握了这三个概念,那么一旦“抽象”自然地嵌入了它们(特别是继承),就无需过多地关注它。

首先,请注意,“抽象”一词具有多种含义,并且陈述的含义不正确,例如,封装需要抽象:当您使用访问修饰符保护a的属性时在公开处理它们的方法(即封装)的同时,该类的用户不再需要担心如何自己处理它们。因此,从某种意义上说,在设计类时,您通过适当地封装方法和属性来抽象-类用户需要做的所有事情都是通过调用正确的方法来使用它,这是一种形式的抽象。

此外,如果您直截了当,多态性也是一种抽象形式:您的代码调用了某个类提供的方法,并且您不知道它将如何起作用,直到实际的类类型为确定(在运行时)。因此,正确指出多态行为是一种抽象。

但是,当抽象概念用作描述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来实现的。

答案 9 :(得分:0)

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

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

答案 10 :(得分:-4)

很容易。

  1. 抽象是抽象的。 “学生”课程是真正学生的抽象。

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