似乎每个使用abstract class
的程序都可以在没有abstract classes
的情况下重写。
例如,
abstract class Animal {
abstract int age();
}
class Dog extends Animal {
@Override int age() { return ... }
}
class Cat extends Animal {
@Override int age() { return ... }
}
如果我必须在Dog和Cat类中实现age
,为什么要在基类中定义它abstract
而不是提供占位符实现:
class Animal {
int age() { throw new Error("override me"); }
}
有没有真实世界的例子说明为什么abstract class
是语言的一部分?提供一些例子来说明这个概念。
答案 0 :(得分:2)
任何可以实例化的类都应符合其合同,以便所有值都符合其类型合同。
例如
Animal a = new Animal(); // Would compile if Animal not abstract.
System.err.println(a.age()); // Use of a value that may not meet its contract.
如果Animal
为abstract
,那么这将产生一个有用的编译时错误,告诉用户他们需要实例化特定的Animal
子类型。
抽象类提供了一种定义接口的方法,无需提供满足合同的完整实现,同时向希望构造实例的人提供明确的信号。
它们提供了一个结构,围绕该结构可以充分实现完整的实现,让作者将完成合同的责任委托给子类型的作者。
答案 1 :(得分:1)
我们不需要需要抽象类,但它们在某些情况下很有用(尽管有时过度使用 - 在我看来,接口通常更合适)。
你age()
的例子可能不是最好的例子,因为计算狗的年龄和猫的年龄可能是相同的,即当前日期减去出生日期。
但请考虑这个例子:假设您的班级move(destination)
中有另一个抽象方法Animal
。然后,Fish
课程可以通过游泳实现此方法,通过步行实现Dog
课程,通过跳跃实现Frog
课程,通过飞行实现Bird
课程。
因此,如果你有一个Animal
个对象的列表,你知道它们都可以移动,但对调用者来说无关紧要如何 a特定的动物移动。