Oop 多态性的真正意义(用途)是什么
我是OOP新手。虽然我了解多态性是什么,但我不能真正使用它。我可以有不同名称的函数。为什么我要尝试在我的应用程序中实现多态性。经典答案:想象一个基类Oop 多态性的真正意义(用途)是什么,oop,polymorphism,Oop,Polymorphism,我是OOP新手。虽然我了解多态性是什么,但我不能真正使用它。我可以有不同名称的函数。为什么我要尝试在我的应用程序中实现多态性。经典答案:想象一个基类Shape。它公开了一个GetArea方法。想象一个正方形类和一个矩形类,以及一个圆形类。与创建单独的GetSquareArea、GetRectangleArea和GetCircleArea方法不同,您只需要在每个派生类中实现一个方法。您不必知道使用的是Shape的哪个确切子类,只需调用GetArea即可得到结果,与具体类型无关 请查看以下代码: #
Shape
。它公开了一个GetArea
方法。想象一个正方形
类和一个矩形
类,以及一个圆形
类。与创建单独的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;
}
#包括
使用名称空间std;
阶级形态
{
公众:
虚拟浮点GetArea()=0;
};
类矩形:公共形状
{
公众:
矩形(浮动a){this->a=a;}
float GetArea(){返回a*a;}
私人:
浮动a;
};
班级圈子:公共形态
{
公众:
圆(浮动r){this->r=r;}
float GetArea(){return 3.14f*r*r;}
私人:
浮子r;
};
int main()
{
形状*a=新圆(1.0f);
形状*b=新矩形(1.0f);
cout GetArea()多态性允许您编写使用对象的代码。然后您可以创建新的类,您的现有代码无需修改即可使用这些类
例如,假设您有一个函数Lib2Groc(vehicle)
,用于将车辆从图书馆引导到杂货店。它需要告诉车辆左转,以便调用turnlight()
在车辆对象上。如果后来有人发明了一种新的车辆,比如气垫船,它可以被Lib2Groc使用,无需修改。您不需要多态性
除非你这么做
那就太可怕了
简单的回答,你会处理很多次:
有人需要浏览一系列资料。比如说,他们要求收集类型为MySpecializedCollectionofWesome的资料。但你一直在处理你的Awesome as列表实例。所以,现在,你必须创建一个MSCOA实例,并用你列表中的每一个Awesome实例填充它。真让人头疼,对吧?
如果他们要一个IEnumerable,你可以给他们一个数组(Awesome[])或者一个列表(List)或者一个可观察到的集合,或者任何你把你的Awesome保存在实现IEnumerable中的东西
多态性的强大功能使您能够实现类型安全,同时又足够灵活,您可以通过多种不同的方式使用实例,而无需创建大量专门处理此类型或该类型的代码。在严格类型化的语言中,多态性对于拥有不同类型对象的列表/集合/数组非常重要s,因为列表/数组本身的类型仅包含正确类型的对象
例如,假设我们有以下情况:
// 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();
}
这两个特征是多态性的核心。 多态性是面向对象程序设计的基础,它意味着一个对象可以作为另一个项目。
继承权
重写/实现父类行为
运行时对象绑定
它的一个主要优点是交换机实现。假设您正在编写一个需要与数据库通信的应用程序。您碰巧定义了一个类,该类为您执行此数据库操作,并希望它执行某些操作,例如添加、删除、修改。您知道数据库可以通过多种方式实现,它可以e与文件系统或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
}
}
让我们看看main如何在两者之间切换
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
}
}
您可以在许多地方使用多态性概念,一个实用的例子是:让您编写图像装饰,您需要支持整个图像组,如jpg、tif、png等。因此,您的应用程序将定义一个接口并直接对其进行操作。您将为每个jpg提供各种实现的一些运行时绑定,tif、pgn等
另一个重要用途是,如果您使用的是java,大多数时候您都会使用列表接口,这样您就可以在应用程序增长或需求变化时使用ArrayList或其他接口。我猜有时会动态调用对象。您不确定对象在经典应用程序中是否是三角形、正方形等形状多边形。例如
所以,为了抛开所有这些东西,我们只需调用派生类的函数,并假设将调用动态类的函数
您不在乎它是正方形、三角形还是矩形。您只关心面积。因此,将根据传递的动态对象调用getArea方法。您是否曾经使用+
添加两个整数,然后使用+
将整数添加到浮点数
您是否曾经登录x.toString()
以帮助您调试某些东西
我想你可能已经很欣赏多态性了,只是不知道它的名字。多态操作最重要的好处之一是扩展能力。
您可以使用相同的操作,而不更改现有接口和实现
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();
}
}