Абстрактные переменные в Java?
Я из С#, где это было легко и возможно.
У меня есть этот код:
public abstract class clsAbstractTable {
public abstract String TAG;
public abstract void init();
}
но Eclipse говорит мне, что я использую незаконный модификатор.
У меня есть этот класс:
public class clsContactGroups extends clsAbstractTable {
}
Я хочу, чтобы переменная и метод были определены таким образом, что Eclipse для подскажите мне, у меня есть нереализованные абстрактные переменные и методы.
Как мне определить свой абстрактный класс, чтобы мне было предложено реализовать тезисы?
РЕДАКТИРОВАТЬ 1
Я создам разные классы для разных таблиц db. Каждый класс должен иметь собственную переменную 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 = "контакты";
и т.д...
Ответы
Ответ 1
Я думаю, ваше замешательство связано с свойствами С# против полей/переменных. В С# вы не можете определять абстрактные поля, даже в абстрактном классе. Тем не менее, вы можете определить абстрактные свойства, поскольку это эффективные методы (например, скомпилированы в get_TAG()
и set_TAG(...)
).
Как напомнили некоторые, у вас никогда не должно быть открытых полей/переменных в ваших классах, даже в С#. Несколько ответов намекнули на то, что я рекомендовал бы, но не дал понять. Вы должны перевести идею на 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:
Вы не можете переопределять унаследованные поля (на С# или Java). Вы также не можете переопределять статические члены, независимо от того, являются ли они полями или методами. Так что это также лучшее решение для этого. Я изменил пример метода init выше, чтобы показать, как это будет использоваться. Еще раз подумайте о методе getXXX в качестве свойства.
Ответ 2
Определите конструктор в абстрактном классе, который задает поле так, чтобы конкретные реализации соответствовали спецификации, требуемой для вызова/переопределения конструктора.
например.
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) {
if (name == null) throw new NullPointerException("Name may not be null");
this.name = name;
}
Ответ 3
В Java (или С++) нет таких объектов, как абстрактные переменные.
Если родительский класс имеет переменную, а дочерний класс расширяет родительский элемент, то дочерний элемент не должен реализовывать переменную. Ему просто нужен доступ к родительскому экземпляру. Либо получить/установить, либо защищенный доступ сделает.
"... поэтому мне должно быть предложено реализовать тезисы"? Если вы расширите абстрактный класс и не сможете реализовать абстрактный метод, компилятор скажет вам либо реализовать его, либо пометить подкласс как абстрактный. Это все подсказки, которые вы получите.
Ответ 4
Просто добавьте этот метод в базовый класс
public abstract class clsAbstractTable {
public abstract String getTAG();
public abstract void init();
}
Теперь каждый класс, который расширяет базовый класс (и не хочет быть абстрактным), должен предоставить TAG
Вы также можете пойти с ответом BalusC
Ответ 5
Лучшее, что вы могли бы сделать, это иметь accessor/mutators для переменной.
Что-то вроде getTAG()
Таким образом, все реализующие классы должны были бы реализовать их.
Абстрактные классы используются для определения абстрактного поведения, а не данных.
Ответ 6
Поскольку реализации переменной не существует, она не может быть абстрактной;)
Ответ 7
Почему вы хотите, чтобы все подклассы определяли переменную? Если каждый подкласс должен иметь его, просто определите его в суперклассе. Кстати, учитывая, что хорошая практика ООП не выставлять поля в любом случае, ваш вопрос имеет еще меньший смысл.
Ответ 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 подклассов, и каждый из них будет иметь эту переменную.
Боковое примечание: не используйте CAPS в качестве имени переменной; общая мудрость заключается в том, что все идентификаторы шапок относятся к константам, то есть к неизменяемым фрагментам данных.
Ответ 9
Чтобы добавить метаданные для каждого класса, возможно, аннотация может быть правильным способом.
Однако вы не можете обеспечить наличие аннотации в интерфейсе, так же, как вы не можете принудительно использовать статические элементы или существование определенного конструктора.
Ответ 10
Существует два способа определения абстрактных свойств в java без выделения свойства как абстрактного.
1st way: Определите параметризованный конструктор в абстрактном классе, например:
public abstract class clsAbstractTable {
private String TAG;
public clsAbstractTable (String TAG) {
this.TAG= TAG;
}
}
При определении параметризованного конструктора в абстрактном классе подклассы вынуждены определять свои собственные конструкторы и вызывать супер-конструктор, следовательно, передавать свой собственный TAG.
Второй способ: определить свойство как метод getter, например:
public abstract class clsAbstractTable {
public abstract String getTAG();
}
Таким образом, значение свойства TAG делегировано для каждого конкретного класса.
Источник: Определить абстрактное свойство в java
Ответ 11
Используйте enums для принудительного выравнивания значений:
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);
}
}
Ответ 12
В моем эксперименте абстрактному классу 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.flyBehavior
или this.attackBehavior
. Вам не нужно переписывать атрибуты в поле атрибутов.
Ответ 13
Нет, Java не поддерживает абстрактные переменные. Это также не имеет большого смысла.
Какое конкретное изменение "реализации" переменной вам ожидает подкласс?
Когда у меня есть переменная abstract
String
в базовом классе, что должен сделать подкласс для того, чтобы сделать ее не абстрактной?