Java 没有抽象方法的抽象类有什么意义?
可以有一个抽象类来实现它的所有方法-其中没有抽象方法 例如: 与使用与具体类相同的类相比,使用这样一个抽象类有什么好处(如果有的话) 我能想到的一点是,当我将它声明为抽象时,它不会被实例化。 然而,我可以通过使它具体化和它的构造函数私有化来达到同样的效果 蒂亚 //================== 编辑:我能想到的另一个用途: 它可能扩展了另一个抽象类,或者实现了一个接口,而没有实现该类的抽象方法——尽管它实现了自己的所有方法。不管它值多少钱 您可以声明实现一个接口而不提供实现,然后每个子级隐式地得到扩展接口 您无法创建此类的实例 将来,您将为所有孩子提供通用的实现Java 没有抽象方法的抽象类有什么意义?,java,inheritance,abstract-class,Java,Inheritance,Abstract Class,可以有一个抽象类来实现它的所有方法-其中没有抽象方法 例如: 与使用与具体类相同的类相比,使用这样一个抽象类有什么好处(如果有的话) 我能想到的一点是,当我将它声明为抽象时,它不会被实例化。 然而,我可以通过使它具体化和它的构造函数私有化来达到同样的效果 蒂亚 //================== 编辑:我能想到的另一个用途: 它可能扩展了另一个抽象类,或者实现了一个接口,而没有实现该类的抽象方法——尽管它实现了自己的所有方法。不管它值多少钱 您可以声明实现一个接口而不提供实现,然后每个子级
它有一个概念上的含义:这个类有一种行为,它本身是没有意义的 诚然,如果没有定义良好的扩展点,即抽象方法,很难想象这样的场景,但有时它会是您问题的一个相当准确的模型 你可以有这样的东西:
public abstract class ObjectWithId {
private final String id;
public ObjectWithId( String id ) {
this.id = id;
}
public final String getId() {
return id;
}
}
然后您可以扩展它来声明具有ID的不同类型的对象。这里您有一个完全指定和实现的行为,但对任何其他行为子类都没有限制
但是请注意,对同一事物建模的更简洁的方法是使用组合而不是继承
public final class ObjectWithId<T> {
private final String id;
private final T ob;
public ObjectWithId( String id, T ob ) {
this.id = id;
this.ob = ob;
}
public String getId() {
return id;
}
public T getObject() {
return ob;
}
}
但是在泛型被引入java版本1.4之前,这将不会像抽象类解决方案那样优雅,明显地更好,因为你必须在类型安全中进行交易。
如果你认为它是实用类,那么它是有用的。通过使类的构造函数私有,可以防止类被实例化。除此之外,没有任何好处。支持它可能只是为了提供语言完整性。实际的区别在于您无法创建它的实例。您必须对其进行子类化,并创建子类的实例 至于你为什么要这么做,实际上。。。我很难想出一个好的理由。您可以说,只有当有人创建了实现某个函数的子类时,该类才有意义。但是为什么不在超类中抽象这个函数呢我不排除有人会提出一些有意义的例子,但我想不出一个。仅仅因为可以编写一段代码并且代码编译成功并不意味着它有意义。我的意思是,我可以写总价格=商品价格*邮政编码+客户高度,单位为7.879,但这并不意味着这样一行代码是有意义的 我们假设您不关心抽象类的方法是实现的还是抽象的,但通过设计,它必须是抽象的,这样当有人扩展它时,他们必须添加更多的方法或重写现有的方法或按原样使用。如果他们不想重写这些方法,那么该抽象类中已经提供了默认行为 在这个抽象类中,您强制执行的唯一标准是-一个人不能实例化那个类,在使用它之前,他们必须有自己唯一的类版本 所以一般来说,实现了很少或全部方法的抽象类要比没有实现任何方法的接口好得多。这是基于这样一种假设,即您将其作为单一继承使用。我们通常使用
public final class ObjectWithId<T> {
private final String id;
private final T ob;
public ObjectWithId( String id, T ob ) {
this.id = id;
this.ob = ob;
}
public String getId() {
return id;
}
public T getObject() {
return ob;
}
}
如果这些语句中的任何一条适用于
你的情况:
您希望在几个密切相关的类之间共享代码。
回答你的问题,
为什么要用具体的抽象方法声明类
一个可能的原因是支持继承而不实际创建对象
假设有两个类,一个是抽象类,另一个是具体类
抽象类:AbsClass
及
混凝土等级:混凝土等级
}
上述两个类的功能应该类似,直到您尝试将其子类化为止
class AbsImplementer extends AbsClass {
//Works fine
}
class ConcImplementer extends ConcreteClass {
//Compilation Error Implicit super constructor ConcreteClass() is not visible
}
考虑类似于不确定Java中的名称:
public abstract class A {
public final void doSomething() {
System.out.println("required");
doOptional();
}
protected void doOptional() {
System.out.println("optional");
}
}
public class B extends A {
@Override
protected void doOptional() {
System.out.println("overridden");
}
}
对于公共API,您只公开一个不能被重写的公共final方法。它在其中执行一些必需的工作,并有一个可选的方法。扩展此类时,只能重写doOptional
调用B.doSomething总是需要打印才能继续
因为doOptional不是抽象的,所以类A需要抽象并没有纯粹的代码原因。但它可能是您的特定项目所需要的。例如,一个基本服务是al
扩展到特定子项目的方法。当从抽象基类派生的类必须具有彼此不同的行为,但该行为不能抽象为驻留在对所有类具有相同签名的方法中时,这可能非常有用。如果不同的行为需要传递不同基元类型的方法,则可能会发生无法共享签名的情况。因为它们使用基本类型,所以不能使用泛型来表示相似性 没有任何抽象方法的抽象基类的行为有点像标记接口,因为它声明实现类必须提供某种行为,而不必将该行为封装在一个新方法中,该方法的签名对于所有实现都是相同的。当实现类有一些共同的行为时,特别是当基类可以为派生类实现它时,您将使用抽象基类而不是标记接口 例如:
abstract class Sender {
protected final void beginMessage() {
...
}
protected final void endMessage() {
...
}
protected final void appendToMessage(int x) {
...
}
}
final class LongSender extends Sender {
public void send(int a, int b, int c) {
beginMessage();
appendToMessage(a);
appendToMessage(b);
appendToMessage(c);
endMessage();
}
}
final class ShortSender extends Sender {
public void send(int a) {
beginMessage();
appendToMessage(a);
endMessage();
}
}
您可能希望提供实例化此类的任何人。如果您将构造函数设置为私有,那么您将使其成为一个单例,或者需要一个公共静态方法来获取类的实例,其中作为抽象类有助于继承…使所有受保护的构造函数注意默认构造函数具有非常相似的特性事实上,这是我做这件事的首选方式。也许这是OP中的一个输入错误。请提供一个例子。我无法想象在允许的情况下接受第一个ok ans什么时候有用。另一个获得了投票权。
public abstract class A {
public final void doSomething() {
System.out.println("required");
doOptional();
}
protected void doOptional() {
System.out.println("optional");
}
}
public class B extends A {
@Override
protected void doOptional() {
System.out.println("overridden");
}
}
abstract class Sender {
protected final void beginMessage() {
...
}
protected final void endMessage() {
...
}
protected final void appendToMessage(int x) {
...
}
}
final class LongSender extends Sender {
public void send(int a, int b, int c) {
beginMessage();
appendToMessage(a);
appendToMessage(b);
appendToMessage(c);
endMessage();
}
}
final class ShortSender extends Sender {
public void send(int a) {
beginMessage();
appendToMessage(a);
endMessage();
}
}