Абстрактные переменные в Java? - PullRequest
43 голосов
/ 03 марта 2010

Я приехал из 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, вот где можно получить некоторые данные. например: TABLENAME = "contacts";
    и т.д ...

Ответы [ 11 ]

58 голосов
/ 03 марта 2010

Определите конструктор в абстрактном классе, который устанавливает поле так, чтобы конкретные реализации соответствовали спецификации, необходимой для вызова / переопределения конструктора.

* 1003 Е.Г. *

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;
}
48 голосов
/ 03 марта 2010

Я думаю, что вы путаете со свойствами C # и полями / переменными. В C # вы не можете определять абстрактные поля, даже в абстрактном классе. Однако вы можете определить абстрактные свойства, поскольку это эффективные методы (например, скомпилированные в get_TAG() и set_TAG(...)).

Как некоторые напомнили, в ваших классах никогда не должно быть открытых полей / переменных, даже в C #. Несколько ответов намекали на то, что я бы порекомендовал, но не ясно дали понять. Вы должны перевести свою идею в Java как свойство JavaBean, используя getTAG (). Тогда ваши подклассы должны будут это реализовать (я также написал проект с табличными классами, которые делают это).

Таким образом, вы можете определить абстрактный класс следующим образом ...

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

}

EDIT

Вы не можете переопределить унаследованные поля (ни в C #, ни в Java). Также вы не можете переопределить статические члены, будь то поля или методы. Так что это также лучшее решение для этого. Я изменил свой пример метода init, приведенный выше, чтобы показать, как он будет использоваться, - снова подумайте о методе getXXX как о свойстве.

6 голосов
/ 03 марта 2010

Нет такой вещи как абстрактные переменные в Java (или C ++).

Если родительский класс имеет переменную, а дочерний класс расширяет родительский, тогда дочернему классу не нужно реализовывать переменную. Ему просто нужен доступ к экземпляру родителя. Подойдет либо get / set, либо защищенный доступ.

"... так что мне нужно предложить ввести тезисы"? Если вы расширяете абстрактный класс и не можете реализовать абстрактный метод, компилятор скажет вам либо реализовать его, либо пометить подкласс как абстрактный. Это все подсказки, которые вы получите.

2 голосов
/ 03 марта 2010

Лучшее, что вы можете сделать, - это использовать методы доступа / мутаторы для переменной.
Что-то вроде getTAG ()
Таким образом, все реализующие классы должны будут их реализовывать.

Абстрактные классы используются для определения абстрактного поведения, а не данных.

2 голосов
/ 03 марта 2010

Просто добавьте этот метод в базовый класс

public abstract class clsAbstractTable {

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

}

Теперь каждый класс, который расширяет базовый класс (и не хочет быть абстрактным), должен предоставлять TAG

Вы также можете пойти с ответом BalusC

1 голос
/ 03 марта 2010

Чтобы добавить метаданные для каждого класса, возможно, аннотация может быть правильным способом.

Однако вы не можете принудительно использовать наличие аннотации в интерфейсе, так же как вы не можете принудительно применитьстатические члены или существование определенного конструктора.

1 голос
/ 03 марта 2010

Измените код на:

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 в качестве имени переменной; Общепринято, что все идентификаторы заглавных букв относятся к константам, то есть неизменяемым частям данных.

1 голос
/ 03 марта 2010

Почему вы хотите, чтобы все подклассы определяли переменную? Если предполагается, что он есть у каждого подкласса, просто определите его в суперклассе. Кстати, учитывая, что это хорошая практика ООП, не раскрывать поля в любом случае, ваш вопрос имеет еще меньше смысла.

1 голос
/ 03 марта 2010

Поскольку реализации переменной нет, она не может быть абстрактной;)

0 голосов
/ 02 декабря 2018

Используйте перечисления для принудительного определения значений, а также для проверки привязки:

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...