我来自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
我希望在每个类中定义一个常量(静态),其名称用abstract定义。
答案 0 :(得分:58)
在抽象类中定义一个构造函数,该构造函数设置字段,以便具体实现符合调用/覆盖构造函数所需的规范。
E.g。
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
。这样,您还可以在抽象类的构造函数中执行(null)检查,以使其更加健壮。 E.g:
public AbstractTable(String name) {
if (name == null) throw new NullPointerException("Name may not be null");
this.name = name;
}
答案 1 :(得分:48)
我认为您的混淆是C#属性与字段/变量。在C#中,即使在抽象类中也无法定义抽象字段。但是,您可以定义抽象属性,因为这些是有效的方法(例如,编译为get_TAG()
和set_TAG(...)
)。
正如一些人提醒过的,你的类中永远不应该有公共字段/变量,即使在C#中也是如此。几个答案暗示了我的建议,但还没有说清楚。您应该使用getTAG()将您的想法转换为Java作为JavaBean属性。然后你的子类必须实现这个(我也编写了一个带有表类的项目)。
所以你可以像这样定义一个抽象类......
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方法视为属性。
答案 2 :(得分:6)
Java(或C ++)中没有抽象变量。
如果父类具有变量,并且子类扩展了父类,则子类不需要实现该变量。它只需要访问父实例。获取/设置或受保护的访问都可以。
“......所以我应该被提示实施摘要”?如果扩展抽象类并且无法实现抽象方法,编译器将告诉您实现它或将子类标记为抽象。这就是你得到的所有提示。
答案 3 :(得分:2)
只需将此方法添加到基类
即可public abstract class clsAbstractTable {
public abstract String getTAG();
public abstract void init();
}
现在,扩展基类(并且不想抽象)的每个类都应提供TAG
您也可以使用BalusC的答案
答案 4 :(得分:2)
你能做的最好的事情就是拥有变量的访问者/变异者
类似 getTAG()的东西
这样,所有实施类都必须实现它们
抽象类用于定义抽象行为而不是数据。
答案 5 :(得分:1)
由于没有变量的实现,它不能是抽象的;)
答案 6 :(得分:1)
为什么要让所有子类定义变量?如果每个子类都应该拥有它,那么只需在超类中定义它。顺便说一句,鉴于OOP的良好做法是不要暴露字段,你的问题就更没意义了。
答案 7 :(得分: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作为变量名;常识是所有大写标识符都是指常量,即不可更改的数据。
答案 8 :(得分:1)
要添加每类元数据,可能注释可能是正确的方法。
但是,您无法在界面中强制执行注释,就像您无法强制执行静态成员或存在特定构造函数一样。
答案 9 :(得分: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);
}
}
答案 10 :(得分:0)
在我的实验中,Java抽象类确实需要指定抽象关键字。相反,将提示“抽象修饰符不能放在此处”的错误。 您可以像普通属性一样指定抽象属性。
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.flyBehavior
或this.attackBehavior
。您无需在属性字段中重写属性。
答案 11 :(得分:-1)
不,Java不支持抽象变量。它也没有多大意义。
对于您希望子类执行的变量“实现”有哪些具体更改?
当我在基类中有一个abstract
String
变量时,子类应该怎么做才能使它成为非抽象的?