代码之家  ›  专栏  ›  技术社区  ›  SeeDerekEngineer

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

  •  0
  • SeeDerekEngineer  · 技术社区  · 4 年前

    给定以下代码:

    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();
        }
    }
    

    当我们最终将vehicle1初始化为Car时,将其声明为Vehicle有什么好处?我们难道不应该把它申报为汽车吗?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Arc    4 年前

    在这个例子中,没有明显的好处。然而,这样做有以下好处:

    1. 通常,您将使用对象调用方法。所以我们有两个选择 ...myFunction(Vehicle vehicle) myFunction(Car car) 。如果您选择使用Car,则限制了可以传递给该方法的类型。这非常重要。请记住,软件发生了很大变化,需求发生了变化,功能也得到了增强。假设现在你有一个闪亮的新物体——一辆法拉利,它扩展了车辆,你不能称之为 myFunction(汽车) 但你可以打电话 myFunction(Vehicle vehicle) 因此,为了使用myFunction进行调用,您必须更改函数签名。有时你无法更改函数签名,因为它是一个库,而你没有源代码。或者你可以改变它,但如果你这样做,你会破坏使用你代码的人。在大型软件开发中,团队是分开的,你必须创建一些类,其他人将使用这些类来完成整个项目。或者,您将创建库并发送给客户。这就是多态性的主要原因:使许多团队能够轻松地协同工作,而不会破坏彼此的代码,并通过使用子类来改进代码,而不会损坏东西。 当你只写一小段代码,不打算与任何人分享,也不打算扩展代码库时,好处不大。然而,这是一个好习惯。

    2. 意图:通过将其声明为Vehicle,你在代码中表明你只关心具有Vehicle行为的东西。也就是说,你可以调用operate()。当你扩展一个类时,你可以向它添加额外的行为/方法。通过将其声明为Vehicle,你将无法调用Car中的任何新方法。请记住,您的代码很可能会被其他人读取(如果它不是您的唯一财产),因此使用Vehicle可以明显看出您只关心可以操作()的东西。

    3. 集合:你经常需要创建对象并将其用作集合。让我们想象一下,你有一场汽车比赛。要启动所有车辆,您可以轻松使用 Vehicle[] 如果你使用Vehicle,把它们都放在里面。如果你使用的是汽车、法拉利、面包车。。。只有当你使用时,你才能塞满它们 Object[] 然后你必须投 ((Vehicle)arrayElement).operate() 而不是仅仅 arrayElement.operate() 我举了一个简单的例子,但我想你会明白的。

    因此,综上所述,仅从你的代码来看,表面上看没有直接的好处,但从上述原因来看,如果你使用Vehicle,就会有好处,现在这样做是有好处的,因为你会养成良好的习惯,更多地考虑面向对象编程和大局。

        2
  •  0
  •   Adam Bickford    4 年前

    在这样的方法中本地声明它没有太大区别。一般来说,通过处理可能有效的最抽象类型的引用,您可以获得更大的灵活性 List<String> foo = new ArrayList<>(); 因为列表就足够了。

    例如,查看Collections.sort()。这需要一个 List 因为列表元素是有序的。它不能只是采取 Collection 因为藏品不能保证被订购,比如 Set 。但它可以使用以下任何实现 列表 ,比如 ArrayList , LinkedList ,等等,因为排序是sort()唯一关心的属性。