我是OOP的新手。虽然我理解多态性是什么,但我无法真正使用它。我可以使用不同名称的函数。我为什么要尝试在我的应用程序中实现多态性。
答案 0 :(得分:21)
经典答案:想象一下基类Shape
。它公开了GetArea
方法。想象一下Square
类和Rectangle
类,以及Circle
类。您可以在每个派生类中实现一个方法,而不是创建单独的GetSquareArea
,GetRectangleArea
和GetCircleArea
方法。您不必知道您使用的Shape
的确切子类,只需调用GetArea
即可获得结果,而不管它是哪种具体类型。
看一下这段代码:
#include <iostream>
using namespace std;
class Shape
{
public:
virtual float GetArea() = 0;
};
class Rectangle : public Shape
{
public:
Rectangle(float a) { this->a = a; }
float GetArea() { return a * a; }
private:
float a;
};
class Circle : public Shape
{
public:
Circle(float r) { this->r = r; }
float GetArea() { return 3.14f * r * r; }
private:
float r;
};
int main()
{
Shape *a = new Circle(1.0f);
Shape *b = new Rectangle(1.0f);
cout << a->GetArea() << endl;
cout << b->GetArea() << endl;
}
这里要注意的一件重要事情是 - 您不必知道您正在使用的类的确切类型,只需要知道基类型,您将获得正确的结果。这在更复杂的系统中也非常有用。
玩得开心!
答案 1 :(得分:16)
您是否曾使用+
添加了两个整数,然后又使用+
将整数添加到浮点数?
您是否曾记录x.toString()
来帮助您调试某些内容?
我认为你可能已经非常了解多态性,只是不知道这个名字。
答案 2 :(得分:7)
在严格类型的语言中,多态性对于拥有不同类型的对象的列表/集合/数组非常重要。这是因为列表/数组本身的类型只包含正确类型的对象。
想象一下,例如我们有以下内容:
// the following is pseudocode M'kay:
class apple;
class banana;
class kitchenKnife;
apple foo;
banana bar;
kitchenKnife bat;
apple *shoppingList = [foo, bar, bat]; // this is illegal because bar and bat is
// not of type apple.
解决这个问题:
class groceries;
class apple inherits groceries;
class banana inherits groceries;
class kitchenKnife inherits groceries;
apple foo;
banana bar;
kitchenKnife bat;
groceries *shoppingList = [foo, bar, bat]; // this is OK
它还使得处理项目列表更加简单。比如说所有杂货都实现了方法price()
,处理这很容易:
int total = 0;
foreach (item in shoppingList) {
total += item.price();
}
这两个特征是多态性的核心。
答案 3 :(得分:5)
多态性是面向对象编程的基础。这意味着一个对象可以作为另一个项目。那么对象如何成为另一个,它可以通过以下
来实现它的一个主要优点是交换机实现。假设您正在编写需要与数据库通信的应用程序。而且您碰巧定义了一个类,它为您执行此数据库操作,并期望执行某些操作,如添加,删除,修改。您知道数据库可以通过多种方式实现,它可以与文件系统或RDBM服务器(如MySQL等)通信。因此,作为程序员,您将定义一个可以使用的接口,例如......
public interface DBOperation {
public void addEmployee(Employee newEmployee);
public void modifyEmployee(int id, Employee newInfo);
public void deleteEmployee(int id);
}
现在您可能有多个实现,假设我们有一个用于RDBMS,另一个用于直接文件系统
public class DBOperation_RDBMS implements DBOperation
// implements DBOperation above stating that you intend to implement all
// methods in DBOperation
public void addEmployee(Employee newEmployee) {
// here I would get JDBC (Java's Interface to RDBMS) handle
// add an entry into database table.
}
public void modifyEmployee(int id, Employee newInfo) {
// here I use JDBC handle to modify employee, and id to index to employee
}
public void deleteEmployee(int id) {
// here I would use JDBC handle to delete an entry
}
}
让文件系统数据库实现
public class DBOperation_FileSystem implements DBOperation
public void addEmployee(Employee newEmployee) {
// here I would Create a file and add a Employee record in to it
}
public void modifyEmployee(int id, Employee newInfo) {
// here I would open file, search for record and change values
}
public void deleteEmployee(int id) {
// here I search entry by id, and delete the record
}
}
让我们看看主要如何在两者之间切换
public class Main {
public static void main(String[] args) throws Exception {
Employee emp = new Employee();
... set employee information
DBOperation dboper = null;
// declare your db operation object, not there is no instance
// associated with it
if(args[0].equals("use_rdbms")) {
dboper = new DBOperation_RDBMS();
// here conditionally, i.e when first argument to program is
// use_rdbms, we instantiate RDBM implementation and associate
// with variable dboper, which delcared as DBOperation.
// this is where runtime binding of polymorphism kicks in
// JVM is allowing this assignment because DBOperation_RDBMS
// has a "is a" relationship with DBOperation.
} else if(args[0].equals("use_fs")) {
dboper = new DBOperation_FileSystem();
// similarly here conditionally we assign a different instance.
} else {
throw new RuntimeException("Dont know which implemnation to use");
}
dboper.addEmployee(emp);
// now dboper is refering to one of the implementation
// based on the if conditions above
// by this point JVM knows dboper variable is associated with
// 'a' implemenation, and it will call appropriate method
}
}
你可以在很多地方使用多态概念,一个例子就是:让你编写图像decorer,你需要支持整组图像,如jpg,tif,png等。所以你的应用程序将定义一个界面和直接工作。并且您将为jpg,tif,pgn等每个实现各种实现的运行时绑定。
另一个重要的用途是,如果您使用的是Java,那么大多数时候您都会使用List接口,这样您就可以在应用程序增长或需求发生变化时立即使用ArrayList或其他界面。
答案 4 :(得分:5)
多态性的优点是客户端代码不需要关心方法的实际实现。 请看下面的例子。 在这里,CarBuilder对ProduceCar()一无所知。一旦给出汽车列表(CarsToProduceList),它将相应地生产所有必需的汽车。
class CarBase
{
public virtual void ProduceCar()
{
Console.WriteLine("don't know how to produce");
}
}
class CarToyota : CarBase
{
public override void ProduceCar()
{
Console.WriteLine("Producing Toyota Car ");
}
}
class CarBmw : CarBase
{
public override void ProduceCar()
{
Console.WriteLine("Producing Bmw Car");
}
}
class CarUnknown : CarBase { }
class CarBuilder
{
public List<CarBase> CarsToProduceList { get; set; }
public void ProduceCars()
{
if (null != CarsToProduceList)
{
foreach (CarBase car in CarsToProduceList)
{
car.ProduceCar();// doesn't know how to produce
}
}
}
}
class Program
{
static void Main(string[] args)
{
CarBuilder carbuilder = new CarBuilder();
carbuilder.CarsToProduceList = new List<CarBase>() { new CarBmw(), new CarToyota(), new CarUnknown() };
carbuilder.ProduceCars();
}
}
答案 5 :(得分:1)
Polymorphism允许您编写使用对象的代码。然后,您可以在以后创建现有代码无需修改即可使用的新类。
例如,假设您有一个功能Lib2Groc(vehicle)
,可以将车辆从图书馆引导到杂货店。它需要告诉车辆向左转,因此它可以在车辆对象上调用TurnLeft()
等。然后,如果有人后来发明了一种新的车辆,比如气垫船,它可以被Lib2Groc
使用而无需修改。
答案 6 :(得分:1)
从多态操作中获得的最重要的好处之一是扩展能力。 您可以使用相同的操作,而不是仅仅因为您需要一些新的东西来改变现有的接口和实现。
我们想要的多态性 - 简化了我们的设计决策,使我们的设计更具可扩展性和优雅性。 您还应该注意开放 - 封闭原则(http://en.wikipedia.org/wiki/Open/closed_principle)和SOLID(http://en.wikipedia.org/wiki/Solid_%28Object_Oriented_Design%29),它们可以帮助您理解关键的OO原则。
P.S。我认为你在谈论“动态多态”(http://en.wikipedia.org/wiki/Dynamic_polymorphism),因为有类似“静态多态”(http://en.wikipedia.org/wiki/Template_metaprogramming#Static_polymorphism)的东西。
答案 7 :(得分:0)
您不需要多态性。
直到你。
然后它的friggen很棒。
简单回答你会多次处理:
有人需要经历一系列的事情。假设他们要求MySpecializedCollectionOfAwesome类型的集合。但是你一直在处理你的Awesome实例列表。所以,现在,你将不得不创建一个MSCOA实例,并用你在List&lt; T&gt;中的每个Awesome实例填充它。对接的痛苦,对吧?
好吧,如果他们要求IEnumerable&lt; Awesome&gt;,你就可以把它们交给很多很棒的Awesome。你可以给它们一个数组(Awesome [])或一个List(List&lt; Awesome&gt;)或一个可观察的Awesome或ANYTHING ELSE集合你保持你的Awesome实现IEnumerable&lt; T&gt;。
多态性的强大功能使您可以保持类型安全,但又足够灵活,您可以使用许多不同方式的实例,而无需创建大量专门处理此类型或类型的代码。
答案 8 :(得分:0)
我猜有时会动态调用对象。您不确定对象在经典形状poly中是否为三角形,正方形等。例。
因此,为了抛弃所有这些东西,我们只需调用派生类的函数并假设将调用其中一个动态类。
你不在乎它是一个sqaure,三角形还是矩形。你只关心这个地区。因此,将根据传递的动态对象调用getArea方法。
答案 9 :(得分:0)
标签式应用
一个很好的应用程序是选项卡式应用程序中的通用按钮(所有选项卡) - 即使我们使用它的浏览器也在实现多态性,因为它不知道我们正在使用的选项卡在编译时(代码中的,换句话说)。它始终在运行时确定(现在!当我们使用浏览器时。)