【问题标题】:Creating Object for abstract class为抽象类创建对象
【发布时间】:2014-09-19 13:06:48
【问题描述】:

我正在审查我的 OOP,我对对象有一个小问题。好吧,我有一个超类Ship,它也是一个抽象类。 Ship 有一些子类,即SubmarineDestroyer 等。

我知道我无法创建 Ship 类的对象,因为它是抽象的。但是为什么以下仍然有效?

Ship s1 = new Submarine("ship 1");

【问题讨论】:

  • 不能实例化抽象类,并不意味着不能拥有该类型的对象。也可以有某个接口的对象,比如List<String> strings = new ArrayList<>();
  • 因为在这一行中,您创建了一个Submarine 类型的对象,然后将其转换为Ship 类型。 SubmarineIS-A Ship
  • 它是多态性 - 你有 Submarine 对象,但你将它视为 Ship。
  • 它有效,因为您正在实例化 Ship 的子类,而不是 Ship 本身。您声明抽象方法以确保每个扩展抽象类的类都将实现此方法。

标签: java oop abstract


【解决方案1】:

线路:Ship s1 = new Submarine("ship 1");

您没有创建抽象类Ship 的对象,它只是指向子类Submarine 的对象的引用。您实际上正在做的是创建子类的对象。

【讨论】:

    【解决方案2】:

    简单来说,抽象类意味着您不能创建此类的新实例。
    但是,仍然可以将对象声明为 Ship编译时类型 vs 运行时类型)以使用多态性,允许你可以做一些有趣的事情,比如包含SubmarineDestroyer(以及更多)的Ship 数组。

    Ship[] army = new Ship[2];
    army[0] = new Submarine("0");
    army[1] = new Destroyer("1");
    
    for( Ship s : army ) {
      s.fire();
    }
    

    在这个示例中,我们可以在两个对象上调用fire(),因为fire()Ship 的一个方法。由于舰船的攻击取决于舰船的类型(潜艇不会像驱逐舰那样开火),因此您设置了Ship 抽象的fire() 方法并在SubmarineDestroyer 中实现它。

    这些技巧在 OOP 中是必不可少的,可让您实现强大的设计模式。如果你是初学者,看看strategy patterntemplate method pattern,几年前它们改变了我对OOP 的看法;)

    希望这个小示例对您有所帮助:)

    【讨论】:

      【解决方案3】:

      这是由于多态性。

      父类的引用可以保存子类对象。但是使用这个引用你可以调用那些在子类中被正确覆盖的方法。

      【讨论】:

        【解决方案4】:

        你应该区分运行时类型和编译时类型。

        假设您有以下语句:

        Ship s1 = new Submarine("ship 1");
        
        • s1编译时类型 是赋值语句左侧的类型,例如编译时类型是Ship。您可以将s1 分配给任何继承Ship 的类型。

        • s1运行时类型 是赋值语句的右侧,例如s1 的运行时类型是Ship具体实现(在您的情况下为Submarine)。

        更多信息:

        【讨论】:

        • +1 突出编译时类型和运行时类型的区别:)
        【解决方案5】:

        仅仅因为您不能实例化抽象类,并不意味着您不能拥有该类型的对象。也可以有某个接口的对象,比如List<String> strings = new ArrayList<>()

        您声明方法抽象是因为默认实现没有意义。

        考虑一个名为shape 的类,它有子类circlesquareshape 有一个面积,但circle 的面积计算方式与square 的面积不同。

        您可以在抽象shape 类中创建一个名为getArea 的抽象方法,并让circlesquare 提供它们的实现。

        【讨论】:

          【解决方案6】:

          s1 是一艘船,您可以使用抽象类中定义的所有方法,但只能使用这些方法。 如果您的 Submarine 类中有其他方法(例如,dive、periscopeUp、...),则无法调用它们,因为它们未在您的抽象 Ship 类中定义。

          使用它主要用于收藏,例如,您现在可以将不同类型的船存储在列表中。

          List<Ship> ships = new ArrayList<Ship>();
          ships.add(new Submarine("sub 1"));
          ships.add(new Destroyer("des 1"));
          

          如果您要定义“List&lt;Submarine&gt; subs”,则只能将 Submarine 类存储在该列表中。

          【讨论】:

            猜你喜欢
            • 2012-11-27
            • 1970-01-01
            • 2016-07-21
            • 2016-07-23
            • 1970-01-01
            • 2017-12-13
            • 1970-01-01
            • 1970-01-01
            • 2012-09-23
            相关资源
            最近更新 更多