Java中的抽象变量?

发布于 2024-08-23 10:26:06 字数 1090 浏览 8 评论 0原文

我来自 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 =“联系人组”;
  • 我创建了第二个类 clsContacts,系统应该提示我实现 TABLENAME,这是获取一些数据的地方。例如:TABLENAME =“联系人”;
    ETC...

I am coming from c# where this was easy, and possible.

I have this code:

public abstract class clsAbstractTable {

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

}

but Eclipse tells me I use illegal modifier.

I have this class:

public class clsContactGroups extends clsAbstractTable {


}

I want the variable and method defined in such way, that Eclipse to prompt me, I have unimplemented abstract variables and methods.

How do I need to define my abstract class so I should be prompted to implement the abstracts?

EDIT 1

I will create different classes for different db tables. Each class should have it's own TABLENAME variable, no exception. I have to make sure this variable is static each time when I create a new class that extends the abstract class.

Then in the abstract class I will have a method eg: init();

If in this init() method I call TABLENAME, it should take the value from the sub-class.

something like this should also work out

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

EDIT 2

I want a constant(static) defined in each class having it's name defined in abstract.

  • I define variable TABLENAME in abstract, but no value given.
  • I create a clsContactGroups, I should be prompted to implement TABLENAME, this is where gets some data. eg: TABLENAME="contactgroups";
  • I create a second class clsContacts, I should be prompted to implement TABLENAME, this is where gets some data. eg: TABLENAME="contacts";
    etc...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

咋地 2024-08-30 10:26:06

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

例如,

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) 检查,以使其更加健壮。例如:

public AbstractTable(String name) {
    Objects.requireNonNull(name, "Name may not be null");
    this.name = name;
}

Define a constructor in the abstract class which sets the field so that the concrete implementations are per the specification required to call/override the constructor.

E.g.

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

When you extend AbstractTable, the class won't compile until you add a constructor which calls super("somename").

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

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

This way the implementors are required to set name. This way you can also do (null)checks in the constructor of the abstract class to make it more robust. E.g:

public AbstractTable(String name) {
    Objects.requireNonNull(name, "Name may not be null");
    this.name = name;
}
夜吻♂芭芘 2024-08-30 10:26:06

我认为您的困惑在于 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 方法视为一个属性。

I think your confusion is with C# properties vs. fields/variables. In C# you cannot define abstract fields, even in an abstract class. You can, however, define abstract properties as these are effectively methods (e.g. compiled to get_TAG() and set_TAG(...)).

As some have reminded, you should never have public fields/variables in your classes, even in C#. Several answers have hinted at what I would recommend, but have not made it clear. You should translate your idea into Java as a JavaBean property, using getTAG(). Then your sub-classes will have to implement this (I also have written a project with table classes that do this).

So you can have an abstract class defined like this...

public abstract class AbstractTable {

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

    ...
}

Then, in any concrete subclasses you would need to define a static final variable (constant) and return that from the getTag(), something like this:

public class SalesTable extends AbstractTable {

    private static final String TABLE_NAME = "Sales";

    public String getTag() {
        return TABLE_NAME;
    }

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

}

EDIT:

You cannot override inherited fields (in either C# or Java). Nor can you override static members, whether they are fields or methods. So this also is the best solution for that. I changed my init method example above to show how this would be used - again, think of the getXXX method as a property.

云柯 2024-08-30 10:26:06

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

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

“……所以应该提示我实施摘要”?如果扩展抽象类但未能实现抽象方法,编译器会告诉您要么实现它,要么将子类标记为抽象。这就是您将得到的所有提示。

No such thing as abstract variables in Java (or C++).

If the parent class has a variable, and a child class extends the parent, then the child doesn't need to implement the variable. It just needs access to the parent's instance. Either get/set or protected access will do.

"...so I should be prompted to implement the abstracts"? If you extend an abstract class and fail to implement an abstract method the compiler will tell you to either implement it or mark the subclass as abstract. That's all the prompting you'll get.

甜味超标? 2024-08-30 10:26:06

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

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

The best you could do is have accessor/mutators for the variable.
Something like getTAG()
That way all implementing classes would have to implement them.

Abstract classes are used to define abstract behaviour not data.

千と千尋 2024-08-30 10:26:06

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

public abstract class clsAbstractTable {

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

}

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

您也可以采用 BalusC 的答案

Just add this method to the base class

public abstract class clsAbstractTable {

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

}

Now every class that extends the base class (and does not want to be abstract) should provide a TAG

You could also go with BalusC's answer

梦毁影碎の 2024-08-30 10:26:06

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

As there is no implementation of a variable it can't be abstract ;)

夏天碎花小短裙 2024-08-30 10:26:06

为什么要让所有子类都定义变量?如果每个子类都应该有它,只需在超类中定义它即可。顺便说一句,考虑到无论如何都不暴露字段是良好的 OOP 实践,你的问题就更没有意义了。

Why do you want all subclasses to define the variable? If every subclass is supposed to have it, just define it in the superclass. BTW, given that it's good OOP practice not to expose fields anyway, your question makes even less sense.

绅刃 2024-08-30 10:26:06

将代码更改为:

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

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

这样,所有继承该类的类都将具有该变量。您可以创建 200 个子类,但每个子类仍将具有此变量。

附注:不要使用大写字母作为变量名;常识是所有大写标识符都引用常量,即不可更改的数据。

Change the code to:

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

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

That way, all of the classes who inherit this class will have this variable. You can do 200 subclasses and still each one of them will have this variable.

Side note: do not use CAPS as variable name; common wisdom is that all caps identifiers refer to constants, i.e. non-changeable pieces of data.

七月上 2024-08-30 10:26:06

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

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

To add per-class metadata, maybe an annotation might be the correct way to go.

However, you can't enforce the presence of an annotation in the interface, just as you can't enforce static members or the existence of a specific constructor.

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

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);
    }
}

Use enums to force values as well to keep bound checks:

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);
    }
}
小巷里的女流氓 2024-08-30 10:26:06

在我的实验中,Java抽象类确实需要指定abstract关键字。反之,会提示“此处不能放置抽象修饰符”的错误。
您可以像普通属性一样指定抽象属性。

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。您不需要重写属性字段中的属性。

In my experiment, Java abstract class does need to specify abstract keyword. Reversely, error that "abstract modifier cannot be put here" will be prompted.
You can specify abstract attributes just like ordinary attributes.

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>();
    }
}

And in subclass, you can directly use these attributes this.flyBehavior or this.attackBehavior. You don't need to rewrite the attributes in attribute field.

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 控制台上看到以下内容:
贝拉正在飞翔!
梅维斯正在飞翔!
鲍里斯坠毁了!
梅维斯还在飞翔!

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

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(); 

}

Then you will have another class:

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();
    }
}

I ran the above code after putting it into separate file names of Duck.java and KhakiCampbell.java of course. After running KhakiCampbell in eclipse I saw the following on the java console:
Bella is flying!
Mavis is flying!
Boris has crashed!
Mavis is still flying!

I hope this answers your questions. You do not need any static variable declarations.

差↓一点笑了 2024-08-30 10:26:06

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

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

当我在基类中有一个 abstract String 变量时,子类应该如何使其成为非抽象变量?

No, Java doesn't support abstract variables. It doesn't really make a lot of sense, either.

What specific change to the "implementation" of a variable to you expect a sub class to do?

When I have a abstract String variable in the base class, what should the sub class do to make it non-abstract?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文