简体   繁体   English

由于多态性,声明不同于初始化 object 的类型有什么好处?

[英]What are the benefits of declaring a different type than the initialization object due to polymorphism?

Given the following code:给定以下代码:

class Vehicle{
    public void operate(){
        System.out.println("The vehicle is being operated.");
    }
}

class Car extends Vehicle{
    public void operate(){
        System.out.println("The car is being operated.");
    }
}

public class Simulation{
    public static void main(String[] args){
        Vehicle vehicle1 = new Car();
        Vehicle vehicle2 = new Vehicle();
        vehicle1.operate();
        vehicle2.operate();
    }
}

What is the benefit of declaring vehicle1 as a Vehicle when we end up initializing it as Car?当我们最终将 vehicle1 初始化为 Car 时,将其声明为 Vehicle 有什么好处? Shouldn't we just declare it as a Car?我们不应该将其声明为汽车吗?

In this example it's not obvious to see the benefit.在这个例子中,看到好处并不明显。 However, doing so has these benefits:但是,这样做有以下好处:

  1. Usually you'll be calling methods with your object.通常你会用你的 object 调用方法。 So we have two options ...myFunction(Vehicle vehicle) or myFunction(Car car) .所以我们有两个选择...myFunction(Vehicle vehicle)myFunction(Car car) If you choose to use Car, you are restricting the type that can be passed to that method.如果您选择使用 Car,您将限制可以传递给该方法的类型。 This is very important.这个非常重要。 Keep in mind software changes a lot, requirements change, enhancements are made.请记住,软件发生了很多变化,需求发生了变化,并进行了增强。 Let's suppose now you have a shiny new object a Ferrari which extends Vehicle, you cannot call myFunction(Car car) but you will be able to call myFunction(Vehicle vehicle) by passing Ferrari.假设现在你有一个 shiny 新 object 一辆法拉利,它扩展了 Vehicle,你不能调用myFunction(Car car) ,但你可以通过 Ferrari 调用myFunction(Vehicle vehicle) So in order to make your call using myFunction you will have to change the function signature.因此,为了使用 myFunction 拨打电话,您必须更改 function 签名。 Sometimes you cannot change the function signature because, well, it is a library and you don't have the source code.有时您无法更改 function 签名,因为它是一个库,而您没有源代码。 Or maybe you can change it but if you do you will break people using your code.或者也许你可以改变它,但如果你这样做,你会破坏使用你的代码的人。 In larger software development, teams are split and you have to create some classes that others will use to complete the whole project.在大型软件开发中,团队是分裂的,您必须创建一些其他人将用来完成整个项目的类。 Or you will create libraries and ship to clients.或者您将创建库并发送给客户。 That's the main reason there is polymorphism: to make it easy for many teams to work together without breaking each others code and also improve on the code by using subclasses without breaking things.这就是存在多态性的主要原因:使许多团队可以轻松地一起工作而不会破坏彼此的代码,并且还可以通过使用子类而不破坏事物来改进代码。 When you are writing only a small piece of code that you are not going to share with anyone and don't plan on expanding that code base, there is not much of a benefit.当您只编写一小段不打算与任何人共享的代码并且不打算扩展该代码库时,没有太大的好处。 However it is a good habit to have.然而,拥有它是一个好习惯。

  2. Intent: by declaring it as Vehicle, you are showing in your code that you only care about something that has the behavior of a Vehicle.ie you can call operate().意图:通过将其声明为车辆,您在代码中表明您只关心具有车辆行为的东西。即您可以调用操作()。 When you extend a class you can add additional behaviors/methods to it.当您扩展 class 时,您可以向其添加其他行为/方法。 By declaring it as Vehicle you won't be able to call any of new methods in Car.通过将其声明为 Vehicle,您将无法调用 Car 中的任何新方法。 Remember that your code will most likely be read by others (if it's not your sole property), so using Vehicle makes it obvious that you only care about something that can operate().请记住,您的代码很可能会被其他人阅读(如果它不是您的唯一财产),因此使用 Vehicle 很明显您只关心可以操作()的东西。

  3. Collections: Very often you need to create objects and use them as a collection. Collections:您经常需要创建对象并将它们用作集合。 Let's imagine you have a race of Vehicles.让我们假设您有一个车辆竞赛。 To make all the Vehicles start, you can easily use Vehicle[] and stuff all of them in there if you use Vehicle.要使所有车辆启动,您可以轻松使用Vehicle[]并将所有车辆都放入其中(如果您使用 Vehicle)。 If you were using the Car, Ferrari, Van... you could only stuff them if you use Object[] and then you will have to cast to ((Vehicle)arrayElement).operate() instead of just arrayElement.operate() .如果您使用的是 Car、Ferrari、Van ......您只能在使用Object[]时填充它们,然后您必须强制转换为((Vehicle)arrayElement).operate()而不仅仅是arrayElement.operate() . I'm giving a simplistic example but I think you'll get the idea.我举了一个简单的例子,但我想你会明白的。

So to conclude, from only your code there is on the surface no direct benefit but from the reasons above there will be a benefit if you use Vehicle and there is benefit to do so now because you will build good habits and think more OOP and about the bigger picture.因此,总而言之,仅从您的代码表面上看没有直接的好处,但从上述原因来看,如果您使用 Vehicle 会有好处,现在这样做是有好处的,因为您将养成良好的习惯并思考更多 OOP 和关于更大的图景。

Declaring it locally in a method like that there isn't much difference.以这样的方法在本地声明它并没有太大区别。 Generally speaking you get more flexibility by working on references of the most abstract type that can possibly work.一般来说,通过处理可能工作的最抽象类型的引用,您可以获得更大的灵活性。 You might see that in code like List<String> foo = new ArrayList<>();您可能会在List<String> foo = new ArrayList<>();这样的代码中看到这一点。 because List is enough.因为列表就足够了。

For example look at Collections.sort().例如查看 Collections.sort()。 It takes a List because list elements are ordered.它需要一个List ,因为列表元素是有序的。 It can't just take Collection because collections aren't guaranteed to be ordered, like Set .它不能只接受Collection因为 collections 不能保证被订购,比如Set But it can use any implementation of List , like ArrayList , LinkedList , etc because ordering is the only property sort() cares about.但它可以使用List的任何实现,例如ArrayListLinkedList等,因为排序是 sort() 唯一关心的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM