【问题标题】:Abstract variables in Java?Java中的抽象变量?
【发布时间】:2011-01-23 04:23:55
【问题描述】:

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

我有这个代码:

public abstract class clsAbstractTable {

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

}

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

我有这门课:

public class clsContactGroups extends clsAbstractTable {


}

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

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

编辑 1

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

然后在抽象类中我会有一个方法 eg: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,这是获取一些数据的地方。例如:TABLENAME="联系人";
    等等……

【问题讨论】:

  • Java 中没有抽象变量之类的东西。抽象方法,是的。
  • 我的示例中的 TAG 变量。我想被提示在其他类上实现它们。
  • 如何提示我在所有类中定义一个 TAG 变量?
  • 我看不出有什么理由不能使用声明为抽象的 getTableName() 之类的方法来完成。
  • 对不起,但这在 C# 中也是不可能的。只有 instance methods(和 setter/getter)可以是抽象的。

标签: java class variables abstract


【解决方案1】:

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

例如

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

【讨论】:

  • 我需要用静态变量来完成。因为变量对于实现的类来说是静态的,就像类的表名一样。我不想每次都将表名传递给构造函数。
  • 静态变量在类的所有实例之间共享。如果您设置它,那么它将在类的所有实例中更改/反映,无论实现。你真的想要这个吗?如果是这样,那么我真的看不到使它们抽象的任何好处……正是由于前面的原因(影响所有实例)。这在技术上也是不可能的,因为它违反了面向对象的意识形态。您要么需要再次学习 Java/OO,要么重新考虑您的方法/设计。
  • 查看我对问题的编辑。我想要在每个类中定义一个常量(表名),并在抽象中定义它的名称。
  • 那么我的回答仍然适用。您无需将其设为静态。这没有任何意义。
  • 对不起,我不明白。因为它是每类数据,例如。表名,而不是每个实例。我认为它需要是静态的,因为它不会改变。
【解决方案2】:

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

【讨论】:

  • +1 我认为这确实回答了 OP 的问题,因为问题的原始前提是错误的(C# 可以有抽象字段)
【解决方案3】:

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

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

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

【讨论】:

  • 我想确保子类定义了该变量。我怎么能确定?
  • @Pentium10:与首先在基类中定义变量相比,这有什么优势?
  • 我将为不同的数据库表创建不同的类。每个类都应该有自己的 TABLENAME 变量,也不例外。每次创建扩展抽象类的新类时,我都必须确保这些变量是静态的。
  • 我怀疑您是否需要每桌一堂课。我相信在内存中创建一个具有多个实例的类就足够了。
【解决方案4】:

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

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

【讨论】:

  • 是的,我要定义抽象行为,我的意思是定义名称,然后在实现层处理数据。
【解决方案5】:

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

public abstract class clsAbstractTable {

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

}

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

你也可以选择 BalusC 的回答

【讨论】:

  • 这不是解决方案。解决方案首先要找出 OP 想要实现的目标。
  • 我编辑了我的问题,希望清楚我想要达到的目标。
  • 我认为这是解决方案。至少是 Java 提供的唯一满足所有要求的一种。每个子类都必须提供一个 getTAG 实现,该实现可以为该子类返回一个字符串常量。在我看来,这甚至比将其保留在原始代码中的每个实例变量中要好。
  • 我不鼓励将 get/set 放在这样的界面中。
  • @Joachim:这似乎有点苛刻。我认为 Lombo 非常了解 OP,getter 方法确实是更好的实现,只是这里没有完全解决。
【解决方案6】:

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

【讨论】:

    【解决方案7】:

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

    【讨论】:

      【解决方案8】:

      将代码改为:

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

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

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

      【讨论】:

      • 当我创建一个新类时,是否会提示我也为该类定义标签?
      • 正如一些人所提醒的,你的类中永远不应该有公共字段/变量 -- public final class 中的 public final 字段没有任何问题,只是一个问题品味。
      • 在阅读了OP的第二次编辑后,我相信他正在寻找Java不支持的类级别的OOP机制。您可以使用 instance 方法完成所有您想要的 OOP,但不能使用 class(Java 中的static)方法。您要么必须 (1) 接受每个 instance 都有自己的变量副本这一事实,要么 (2) 制作一个全局 HashMap 以包含类名和 TAG 值之间的映射以班级为单位。两者都不完美,但是,嘿,没有人说Java懂英语。 ;)
      【解决方案9】:

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

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

      【讨论】:

      • 你能举个例子吗?我很想看看它是如何工作的。
      【解决方案10】:

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

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

      【讨论】:

        【解决方案11】:

        在我的实验中,Java 抽象类确实需要指定 abstract 关键字。反之则会提示“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这些属性。您不需要重写属性字段中的属性。

        【讨论】:

          【解决方案12】:
          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 控制台上看到了以下内容:
          贝拉在飞!
          Mavis 飞起来了!
          鲍里斯坠毁了!
          Mavis 还在飞!

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

          【讨论】:

            【解决方案13】:

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

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

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

            【讨论】:

            • 我想确保子类定义了那个变量。
            • @Pentium10:你已经说过了,但是为什么呢?会有什么好处?为什么不在基类中定义呢?
            • 我想在子类中赋予价值。
            • 因为子类可能有不同的值,但他想确保每个子类都有一个值?
            猜你喜欢
            • 1970-01-01
            • 2010-09-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-23
            • 2011-09-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多