web-dev-qa-db-fra.com

Variables abstraites en Java?

Je viens de c # où c'était facile et possible.

J'ai ce code:

public abstract class clsAbstractTable {

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

}

mais Eclipse me dit que j'utilise un modificateur illégal. 

J'ai cette classe:

public class clsContactGroups extends clsAbstractTable {


}

Je veux que la variable et la méthode soient définies de manière à ce que Eclipse puisse Prompt me, j'ai des méthodes abstraites variables abstraites.

Comment dois-je définir ma classe d’abrégés pour qu’on me demande d’implémenter les abrégés?

EDIT 1

Je vais créer différentes classes pour différentes tables de base de données. Chaque classe doit avoir sa propre variable TABLENAME, sans exception. Je dois m'assurer que cette variable est statique à chaque fois que je crée une nouvelle classe qui étend la classe abstraite.

Ensuite, dans la classe abstraite, j'aurai une méthode, par exemple: init ();

Si dans cette méthode init () j'appelle TABLENAME, il devrait prendre la valeur de la sous-classe.

quelque chose comme ça devrait aussi marcher

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

EDIT 2

Je veux une constante (statique) définie dans chaque classe dont le nom est défini de manière abstraite. 

  • Je définis la variable TABLENAME en résumé, mais aucune valeur n’est donnée.
  • Je crée un clsContactGroups, je devrais être invité à implémenter TABLENAME, c’est là qu’il faut récupérer certaines données. Par exemple: TABLENAME = "contactgroups";
  • Je crée une seconde classe clsContacts, je devrais être invité à implémenter TABLENAME, c'est ici que certaines données sont récupérées. Exemple: TABLENAME = "contacts";
    etc...
42
Pentium10

Je pense que votre confusion est entre les propriétés C # et les champs/variables. En C #, vous ne pouvez pas définir de champs abstraits, même dans une classe abstraite. Vous pouvez toutefois définir des propriétés abstraites car il s’agit bien de méthodes (par exemple, compilées en get_TAG() et set_TAG(...)).

Comme certains l'ont rappelé, vous ne devriez jamais avoir de champs/variables publics dans vos classes, même en C #. Plusieurs réponses ont fait allusion à ce que je recommanderais, mais ne l'ont pas précisé. Vous devez traduire votre idée en Java en tant que propriété JavaBean, à l'aide de getTAG (). Ensuite, vos sous-classes devront l'implémenter (j'ai également écrit un projet avec des classes de table qui le font).

Vous pouvez donc définir une classe abstraite comme ceci ...

public abstract class AbstractTable {

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

    ...
}

Ensuite, dans toute sous-classe concrète, vous devrez définir une variable finale statique (constante) et la renvoyer à partir de la fonction 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();
        ...
    }

}

MODIFIER:

Vous ne pouvez pas remplacer les champs hérités (en C # ou en Java). Vous ne pouvez pas non plus remplacer des membres statiques, qu’il s’agisse de champs ou de méthodes. C'est donc aussi la meilleure solution pour cela. J'ai changé mon exemple de méthode init ci-dessus pour montrer comment cela serait utilisé. Encore une fois, pensez à la méthode getXXX en tant que propriété.

47
Kevin Brock

Définissez un constructeur dans la classe abstraite qui définit le champ de sorte que les implémentations concrètes correspondent à la spécification requise pour appeler/remplacer le constructeur.

Par exemple.

public abstract class AbstractTable {
    protected String name;

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

Lorsque vous étendez AbstractTable, la classe ne se compilera pas tant que vous n'aurez pas ajouté de constructeur qui appelle super("somename").

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

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

De cette façon, les développeurs doivent définir name. De cette façon, vous pouvez également effectuer des vérifications (nulles) dans le constructeur de la classe abstraite pour la rendre plus robuste. Par exemple:

public AbstractTable(String name) {
    if (name == null) throw new NullPointerException("Name may not be null");
    this.name = name;
}
58
BalusC

Aucune variable abstraite en Java (ou C++).

Si la classe parent a une variable et qu'une classe enfant étend le parent, l'enfant n'a pas besoin d'implémenter la variable. Il suffit juste d'avoir accès à l'instance du parent. Obtenir/définir ou un accès protégé fera l'affaire.

"... donc je devrais être invité à mettre en œuvre les résumés"? Si vous étendez une classe abstraite sans réussir à implémenter une méthode abstraite, le compilateur vous demandera de l'implémenter ou de marquer la sous-classe comme abstraite. C'est tout ce que vous obtiendrez.

6
duffymo

Il suffit d'ajouter cette méthode à la classe de base

public abstract class clsAbstractTable {

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

}

Maintenant, chaque classe qui étend la classe de base (et ne veut pas être abstraite) devrait fournir un TAG

Vous pouvez aussi aller avec la réponse de BalusC

2
Lombo

Le mieux que vous puissiez faire est d’avoir des accesseurs/mutateurs pour la variable.
Quelque chose comme getTAG ()
Ainsi, toutes les classes implémentantes devraient les implémenter.

Les classes abstraites sont utilisées pour définir un comportement abstrait et non des données.

2
Padmarag

Pourquoi voulez-vous que toutes les sous-classes définissent la variable? Si chaque sous-classe est supposée l'avoir, définissez-la simplement dans la superclasse. BTW, étant donné que c’est une bonne OOP pratique de ne pas exposer les champs de toute façon, votre question a encore moins de sens.

1

Changer le code en:

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

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

De cette façon, toutes les classes qui hériteront de cette classe auront cette variable. Vous pouvez créer 200 sous-classes et chacune d’entre elles aura cette variable.

Note latérale: n'utilisez pas CAPS comme nom de variable; Il est généralement admis que tous les identificateurs en majuscules font référence à des constantes, c'est-à-dire des données non modifiables.

1
dimitarvp

Pour ajouter des métadonnées par classe, peut-être une annotation serait-elle la bonne façon de procéder.

Cependant, vous ne pouvez pas imposer la présence d'une annotation dans l'interface, tout comme vous ne pouvez pas imposer de membres statiques ni l'existence d'un constructeur spécifique.

1
Joachim Sauer

Comme il n’ya pas d’implémentation de variable, cela ne peut être abstrait;)

1
Tomas Vana

Utilisez des énumérations pour forcer les valeurs et conserver les contrôles liés:

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