60

我来自 c#,这很容易,而且可能。

我有这个代码:

public abstract class clsAbstractTable {

    public abstract String TAG;
    public abstract void init();

}

但 Eclipse 告诉我我使用了非法修饰符。

我有这堂课:

public class clsContactGroups extends clsAbstractTable {


}

我想要以这种方式定义的变量和方法,让 Eclipse提示我,我有未实现的抽象变量和方法。

我需要如何定义我的抽象类,以便提示我实现抽象?

编辑 1

我将为不同的数据库表创建不同的类。每个类都应该有自己的 TABLENAME 变量,也不例外。每次创建扩展抽象类的新类时,我都必须确保这个变量是静态的。

然后在抽象类中我将有一个方法,例如:init();

如果在这个 init() 方法中我调用 TABLENAME,它应该从子类中获取值。

这样的事情也应该解决

String tablename=(clsAbstract)objItem.TABLENAME;
// where objItem can be any class that extended clsAbstract;

编辑 2

我想要在每个类中定义一个常量(静态),并在抽象中定义它的名称。

  • 我在抽象中定义了变量 TABLENAME,但没有给出值。
  • 我创建了一个 clsContactGroups,应该提示我实现 TABLENAME,这是获取一些数据的地方。例如:TABLENAME="contactgroups";
  • 我创建了第二个类 clsContacts,应该提示我实现 TABLENAME,这是获取一些数据的地方。例如:表名=“联系人”;
    ETC...
4

13 回答 13

63

在设置字段的抽象类中定义一个构造函数,以便具体实现符合调用/覆盖构造函数所需的规范。

例如

public abstract class AbstractTable {
    protected String name;

    public AbstractTable(String name) {
        this.name = name;
    }
}

当您扩展AbstractTable时,该类将不会编译,直到您添加一个调用super("somename").

public class ConcreteTable extends AbstractTable {
    private static final String NAME = "concreteTable";

    public ConcreteTable() {
        super(NAME);
    }
}

这种方式要求实现者设置name. 这样,您还可以在抽象类的构造函数中进行(空)检查,以使其更加健壮。例如:

public AbstractTable(String name) {
    if (name == null) throw new NullPointerException("Name may not be null");
    this.name = name;
}
于 2010-03-03T12:14:57.310 回答
53

我认为您的困惑在于 C# 属性与字段/变量。在 C# 中,您不能定义抽象字段,即使在抽象类中也是如此。但是,您可以定义抽象属性,因为它们是有效的方法(例如编译为get_TAG()set_TAG(...))。

正如一些人所提醒的那样,即使在 C# 中,也不应该在类中包含公共字段/变量。几个答案暗示了我的建议,但没有说清楚。您应该使用 getTAG() 将您的想法作为 JavaBean 属性转换为 Java。然后你的子类将不得不实现这个(我也写了一个表类的项目来做到这一点)。

所以你可以有一个像这样定义的抽象类......

public abstract class AbstractTable {

    public abstract String getTag();
    public abstract void init();

    ...
}

然后,在任何具体的子类中,您需要定义一个静态最终变量(常量)并从 中返回它getTag(),如下所示:

public class SalesTable extends AbstractTable {

    private static final String TABLE_NAME = "Sales";

    public String getTag() {
        return TABLE_NAME;
    }

    public void init() {
        ...
        String tableName = getTag();
        ...
    }

}

编辑

您不能覆盖继承的字段(在 C# 或 Java 中)。您也不能覆盖静态成员,无论它们是字段还是方法。所以这也是最好的解决方案。我更改了上面的 init 方法示例以显示如何使用它 - 再次将 getXXX 方法视为一个属性。

于 2010-03-03T12:49:46.380 回答
11

Java(或 C++)中没有抽象变量之类的东西。

如果父类有一个变量,而子类扩展了父类,则子类不需要实现该变量。它只需要访问父实例。获取/设置或受保护的访问都可以。

“......所以我应该被提示实施摘要”?如果你扩展了一个抽象类并且没有实现一个抽象方法,编译器会告诉你要么实现它,要么将子类标记为抽象。这就是你会得到的所有提示。

于 2010-03-03T12:14:31.910 回答
3

您能做的最好的事情就是为变量设置访问器/修改器。
getTAG()
这样的东西所有实现类都必须实现它们。

抽象类用于定义抽象行为而不是数据。

于 2010-03-03T12:15:27.947 回答
2

只需将此方法添加到基类中

public abstract class clsAbstractTable {

    public abstract String getTAG();
    public abstract void init();

}

现在每个扩展基类(并且不想成为抽象类)的类都应该提供一个 TAG

你也可以选择 BalusC 的回答

于 2010-03-03T12:15:03.547 回答
1

由于没有变量的实现,它不能是抽象的;)

于 2010-03-03T12:13:31.413 回答
1

为什么要所有子类都定义变量?如果每个子类都应该有它,只需在超类中定义它。顺便说一句,鉴于无论如何都不公开字段是一种很好的 OOP 做法,你的问题就更没有意义了。

于 2010-03-03T12:17:10.673 回答
1

将代码更改为:

public abstract class clsAbstractTable {
  protected String TAG;
  public abstract void init();
}

public class clsContactGroups extends clsAbstractTable {
  public String doSomething() {
    return TAG + "<something else>";
  }
}

这样,所有继承这个类的类都会有这个变量。你可以做 200 个子类,但仍然每个子类都有这个变量。

旁注:不要使用 CAPS 作为变量名;普遍的看法是所有大写标识符都指的是常量,即不可更改的数据片段。

于 2010-03-03T12:19:49.110 回答
1

要添加每个类的元数据,也许注释可能是正确的方法。

但是,您不能强制在接口中存在注释,就像您不能强制静态成员或特定构造函数的存在一样。

于 2010-03-03T13:02:47.687 回答
0

使用枚举来强制值以及保持绑定检查:

enum Speed {
    HIGH, LOW;
}
private abstract  class SuperClass {
    Speed speed;
    SuperClass(Speed speed) {
        this.speed = speed;
    }
}
private class ChildClass extends SuperClass {
    ChildClass(Speed speed) {
        super(speed);
    }
}
于 2018-12-02T00:25:12.363 回答
0

在我的实验中,Java 抽象类确实需要指定抽象关键字。反之则会提示“abstract modifier cannot be put here”的错误。您可以像指定普通属性一样指定抽象属性。

public abstract class Duck implements Quackable, Observable {
    // observerList should keep the list of observers watching this duck 
    List<Observer> observerList;

    public AttackBehavior attackBehavior;
    public FlyBehavior flyBehavior;

    public Duck() {
        observerList = new ArrayList<Observer>();
    }
}

而在子类中,您可以直接使用这些属性this.flyBehaviorthis.attackBehavior. 您不需要重写属性字段中的属性。

于 2019-09-02T04:54:43.780 回答
0
public abstract class Duck 
{
    /** This is not static. */
    private String duckName = "";

    /** Abstract Constructor. */
    public Duck(final String name) 
    {
        duckName = name;
    }

    /** Accessor method. */
    public String getName()
    {
         return duckName;
    }

    /** An example of an abstract method that has to be made concrete. */
    public abstract void fly(); 

}

然后你将有另一堂课:

public class KhakiCampbell extends Duck
{
    // Constructor
    public KhakiCampbell(final String name)
    {
        super(name);
    }

    @Override
    public void fly()
    {
        /** Do something simple. */
       System.out.println(getName() + " is flying!");
    }
 
    /** This is something that only Khaki Cambell ducks do, of course, joke!. */
    public void crash()
    {
       /** Do something simple. */
       System.out.println(getName() + " has crashed!");
    }
 
    /** Keep going. */
    public void stillFly()
    {
        /** Do something simple. */
        System.out.println(getName() + " is still flying!");
    }

    public static void main(String[] args)
    {
        KhakiCampbell  duck = new KhakiCampbell("Bella");
        KhakiCampbell  mavis = new KhakiCampbell("Mavis");
        KhakiCampbell  boris = new KhakiCampbell("Boris");
        duck.fly();
        mavis.fly();
        boris.crash();
        mavis.stillFly();
    }
}

当然,我在将上面的代码放入 Duck.java 和 KhakiCampbell.java 的单独文件名之后运行了上面的代码。在 Eclipse 中运行 KhakiCampbell 后,我在 Java 控制台上看到以下内容:
Bella is fly!
马维斯在飞!
鲍里斯崩溃了!
马维斯还在飞!

我希望这回答了你的问题。您不需要任何静态变量声明。

于 2022-01-18T14:15:01.677 回答
-1

不,Java 不支持抽象变量。这也没有多大意义。

您期望子类对变量的“实现”进行哪些具体更改?

当我abstract String在基类中有一个变量时,子类应该怎么做才能使其非抽象?

于 2010-03-03T12:13:38.153 回答