大约两个月前,我才刚开始使用Java,而我正尝试着更多地理解抽象类。我了解抽象及其实现的基本概念,但是我不明白的是,为什么抽象类扩展了另一个抽象类以及它添加了哪些功能。另外,我看到了一个抽象类,该抽象类扩展了另一个抽象类,但是它仅实现另一个抽象类的一个功能。
我确实在查找示例代码,但是它们仅显示实现,而没有任何解释:
public abstract class Beverage {
String description = "Beverage";
public String getDescription(){
return description;
}
public abstract double cost();
}
// abstract class CondimentDecorator
public abstract class CondimentDecorator extends Beverage {
@Override
public abstract String getDescription();
}
如您所见,抽象类CondimentDecorator
并没有实现Beverage
抽象类中的所有功能。它仅实现getDescription()
函数。但是,如果CondimentDecorator
是具体的,则将需要实现Beverage
抽象类内部的所有功能。
答案 0 :(得分:4)
当一个抽象类扩展另一个抽象类时,这完全没问题。这只是意味着它详细说明基于旧类的行为新类的行为。但是它仍然不是一个完整的对象,因为它的某些行为仍然未知。
类似于现实世界。
假设您有一个Vehicle
班。它可以是任何车辆:汽车,飞机,公共汽车,自行车等。这是您的抽象类。现在可以使用吗?不,因为您不知道是必须踩踏板还是转动方向盘。
现在,您创建另一个类,例如Car extends Vehicle
。现在可以使用吗?可能吧,但是您仍然不知道它是卡车还是客车。但是你知道它有方向盘。
最后,当您再创建一个类时,例如说MySuperPassengerCar extends Car
,您确切地知道这是什么对象,如何使用它以及它具有什么方法。
答案 1 :(得分:2)
Abstract类定义抽象方法。任何扩展另一个类的类都可以通过添加更多行为来增强超类。如果子类是抽象的,则可以添加一些抽象的行为。
抽象方法就像合同。其他代码可以使用现有代码,并可以依赖它。具体类必须通过提供实现来遵守合同。
下面举个例子看看。
public abstract class SuperAbstract {
public void nonAbstract(){
// some code
}
public abstract void contract();
}
public abstract class SubAbstract extends SuperAbstract{
public void additionalNonAbstract()
// some code
}
public abstract void additionalContract();
}
public class Concrete extends SubAbstract{
public void contract(){
// implementation
}
public void additionalContract(){
//implementation
}
}
// although below is allowed and sometimes when we use an external library then this is one of the way but still this is not a good practice.
// dependencies should be on abstractions only and not on concrete implementation
public abstract class AnotherAbstract extends Concrete{
public void someMethod(){
//some code
}
public abstract void oneMoreContract();
}
public class ConcreteA extends AnotherAbstract{
public void oneMoreContract(){
//some implementation
}
}
现在请注意,我们总共定义了3个合约,ConcreteA
具有所有实现。还要注意,由于Concrete
为方法contract
和additionalContract
提供了实现,因此这些实现被ConcreteA
消费者代码可以轻松地依赖抽象。让我们在用户代码(消费者代码)中查看
public class Consumer{
public void m1(SuperAbstract c)
c.contract();
c.nonAbstract();
}
public void m2(AnotherAbstract c){
c.contract();
c.nonAbstract();
c.oneMoreContract();
c.additionalContract();
}
}
现在让我们看一下提供依赖性的接线代码
public class Main{
public static void main(String[] args){
Consumer c = new Consumer();
c.m1(new Concrete());
c.m1(new ConcreteA());
c.m2(new ConcreteA());
}
}
答案 2 :(得分:1)
抽象类不必执行任何操作。可以,但是没有这样的要求。唯一要做的就是在具体类中提供接口和抽象类的抽象方法的实现。在复杂的层次结构中,尽管可以在中间抽象类中实现某些抽象方法,但并非所有内容都必须在具体类中。