为抽象类创建对象
我在回顾我的面向对象,并对对象有一些疑问。那么我有一个超类Ship
这也是一个抽象类。船有一些子类,即Submarine
,Destroyer
等。为抽象类创建对象
我知道我不能创建Ship类的对象,因为它是抽象的。但为什么以下仍然有效?
Ship s1 = new Submarine("ship 1");
简单来说,抽象类意味着你不能创建这个类的新实例。
但是,它仍然可以声明对象为Ship
(编译时类型 VS 运行时类型)使用多态性,允许你做一些有趣的东西,像Ship
数组,它包含两个Submarine
和Destroyer
(还有更多)。
Ship[] army = new Ship[2];
army[0] = new Submarine("0");
army[1] = new Destroyer("1");
for(Ship s : army) {
s.fire();
}
在此示例中,我们可以在两个对象调用fire()
因为fire()
是Ship
的方法。由于船只的攻击取决于船只的类型(潜艇不会像驱逐舰一样发射),因此您将fire()
方法设为Ship
摘要并在Submarine
和Destroyer
中实施。
这些技巧在OOP中是必不可少的,并且允许您实现强大的设计模式。如果你是一个初学者,着眼于strategy pattern和template method pattern,他们几年前改变了我的OOP的愿景;)
希望这个小样本可以帮助你:)
行:Ship s1 = new Submarine("ship 1");
没有创建抽象类Ship
,其仅仅是一个参考,它指向对象儿童类Submarine
的对象。你正在做的是创建子类的对象。
这是由于多态性。
父类的引用可以容纳子类对象。但是使用此引用可以调用在子类中被正确覆盖的方法。
您应该区分运行时类型和编译时类型。
比方说,你有下面的语句:
Ship s1 = new Submarine("ship 1");
的编译时类型的
s1
是分配statment,例如的左手侧类型编译时的类型是Ship
。您可以将s1
分配给继承Ship
的任何类型。运行时类型的
s1
是赋值语句的右侧,例如,s1
的运行时间类型是具体执行Ship
(在你的情况 -Submarine
)。
更多信息:
+1以突出显示编译时类型和运行时类型之间的区别:) – NiziL 2014-09-19 13:21:09
只是因为你不能实例化一个抽象类,并不意味着你不能有一个类型的对象。您也可以拥有某个界面的对象,如List<String> strings = new ArrayList<>()
您声明了一个抽象方法,因为默认实现没有意义。
考虑一个名为shape
的类,其子类circle
和square
。 A shape
有一个面积,但circle
的面积计算与square
的面积不同。
您可以在抽象类shape
创建一个名为getArea
抽象方法,让circle
和square
提供其执行情况。
s1是一艘船,您可以使用抽象类中定义的所有方法,但只能使用这些方法。 如果您的Submarine类中有其他方法(例如:dive,periscopeUp,...),则不能调用它们,因为它们未在抽象Ship类中定义。
使用此功能主要适用于集合,例如,您现在可以在列表中存储不同类型的Ship。
List<Ship> ships = new ArrayList<Ship>();
ships.add(new Submarine("sub 1"));
ships.add(new Destroyer("des 1"));
如果您需要定义一个“List<Submarine> subs
”你只能存储潜艇在该列表中的类。
只是因为你不能实例化一个抽象类,并不意味着你不能拥有这种类型的对象。你也可以拥有某个接口的对象,比如'List strings = new ArrayList ();' –
Davio
2014-09-19 13:10:42
因为在这一行你创建了一个'Submarine'类型的对象,然后将它转换为'Ship'类型。 '潜艇'是一艘'船' – SimY4 2014-09-19 13:11:12
阅读这一个:http://stackoverflow.com/questions/4321386/create-object-of-abstract-class-and-interface – 2014-09-19 13:11:47