Java 为抽象类创建对象

Java 为抽象类创建对象,java,oop,abstract,Java,Oop,Abstract,我在回顾我的OOP,我有一个关于对象的小问题。我有一个超级类Ship,它也是一个抽象类。船舶有一些子类,即潜艇、驱逐舰等等 我知道我不能创建Ship类的对象,因为它是抽象的。但为什么下面的方法仍然有效 Ship s1 = new Submarine("ship 1"); 行:船s1=新潜艇(“船1”) 您并没有创建抽象类Ship的对象,它只是指向子类subside对象的引用。实际上,您所做的是创建子类的对象 行:船s1=新潜艇(“船1”) 您并没有创建抽象类Ship的对象,它只是指向子类sub

我在回顾我的OOP,我有一个关于对象的小问题。我有一个超级类
Ship
,它也是一个抽象类。船舶有一些子类,即潜艇、驱逐舰等等

我知道我不能创建Ship类的对象,因为它是抽象的。但为什么下面的方法仍然有效

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

行:
船s1=新潜艇(“船1”)


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

行:
船s1=新潜艇(“船1”)


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

这是由于多态性造成的


父类的引用可以保存子类对象。但是使用此引用可以调用在子类中正确重写的方法。

这是由于多态性造成的


父类的引用可以保存子类对象。但是使用此引用可以调用在子类中正确重写的方法。

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

假设你有以下陈述:

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

  • s1
    的运行时类型是赋值语句的右侧,例如
    s1
    的运行时类型是
    船舶
    的具体实现(在您的例子中是-
    潜艇

更多信息:


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

假设你有以下陈述:

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

  • s1
    的运行时类型是赋值语句的右侧,例如
    s1
    的运行时类型是
    船舶
    的具体实现(在您的例子中是-
    潜艇

更多信息:


    • 不能实例化抽象类并不意味着不能拥有该类型的对象。您还可以拥有特定接口的对象,如
      List strings=new ArrayList()

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

      考虑一个名为
      shape
      的类,其子类为
      circle
      square
      形状
      有一个面积,但
      的面积计算方法与
      正方形
      不同


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

      仅仅因为您不能实例化抽象类,并不意味着您不能拥有该类型的对象。您还可以拥有特定接口的对象,如
      List strings=new ArrayList()

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

      考虑一个名为
      shape
      的类,其子类为
      circle
      square
      形状
      有一个面积,但
      的面积计算方法与
      正方形
      不同


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

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

      使用它主要是方便收集,例如,您现在可以在列表中存储不同类型的船舶

      List<Ship> ships = new ArrayList<Ship>();
      ships.add(new Submarine("sub 1"));
      ships.add(new Destroyer("des 1"));
      
      List ships=new ArrayList();
      船舶。增加(新潜艇(“sub 1”);
      新增(新驱逐舰(“des 1”);
      

      如果要定义“
      列表subs
      ”,则只能在该列表中存储subside类。

      s1是一个ship,可以使用抽象类中定义的所有方法,但只能使用那些方法。 如果在潜艇类中有其他方法(例如,dive、periscopeUp等),则无法调用它们,因为它们未在抽象的Ship类中定义

      使用它主要是方便收集,例如,您现在可以在列表中存储不同类型的船舶

      List<Ship> ships = new ArrayList<Ship>();
      ships.add(new Submarine("sub 1"));
      ships.add(new Destroyer("des 1"));
      
      List ships=new ArrayList();
      船舶。增加(新潜艇(“sub 1”);
      新增(新驱逐舰(“des 1”);
      

      如果要定义“
      列表subs
      ”,则只能在该列表中存储subside类。

      简单来说,抽象类意味着您无法创建该类的新实例。
      然而,仍然可以将一个对象声明为
      Ship
      (编译时类型与运行时类型)以使用多态性,这允许您执行一些有趣的操作,例如
      Ship
      数组,其中包含
      潜艇
      驱逐舰
      (以及更多)

      在本示例中,我们可以对两个对象调用
      fire()
      ,因为
      fire()
      Ship
      的一种方法。由于船舶的攻击取决于船舶的类型(潜艇不会