Veuillez patienter, c'est la première fois que je traite de l'héritage en Java. :)

J'ai la superclasse suivante qui identifie les navires et renvoie un nom du navire et sa longueur:

public class Ship {

    private String name="";
    private int length=0;

    public Ship(String name, int length) {
        this.setName(name);
        this.length = length;
    }

    public static String getName() {
        return name;
    }

    public void setName(String name) {
        Ship.name = name;
    }

    public String toString() {
        return " Ship "+name+" l="+ length ;
    }

}

Cela se fait en créant un objet tel que:

Ship SSAnne = new Ship("S.S. Anne", 45);

Ensuite, j'ai des "sous-classes" qui s'étendent de ma superclasse qui définissent les objets Container Ships, Tankers et Cruise Ships. Voici ma sous-classe pour les porte-conteneurs (les autres types de navires sont identiques, sauf pour des noms de variables différents):

public class ContainerShip extends Ship {

    private int teu=0;

    public ContainerShip(String string, int length, int teu) {
        super(getName(), length);
        this.teu = teu;
    }

    public void setName(String name) {
        ContainerShip.name = name;
    }

    public String toString() {
        return super.toString()+" container carrier with "+teu+" TEU";
    }

}

Ces sous-classes sont appelées comme ceci:

ContainerShip dave = new ContainerShip("Dave Oest", 100, 2000);

Où une variable supplémentaire est ajoutée et les deux premiers arguments sont les mêmes variables de la superclasse.

Mon problème est avec mes getters et setters pour la variable "name". Lorsque j'exécute mon code, il génère le nom "S.S. Anne" pour tous les objets, même les objets des sous-classes. Je n'arrive pas à obtenir le nom des vaisseaux de mes sous-classes.

Quelqu'un peut-il m'aider à configurer correctement les getters et les setters dans mes sous-classes?


@GBlodgett:

public class Ship {

    private String name="";
    private int length=0;

    public Ship(String name, int length) {
        this.setName(name);
        this.length = length;
    }

    public void getName(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return " Ship "+name+" l="+ length ;
    }

}

public class ContainerShip extends Ship {

    private int teu=0;

    public ContainerShip(String string, int length, int teu) {
        super(getName(), length);
        this.teu = teu;
    }

    public void getName(String name) {
        this.name = name;
    }

    public void setName(String name) {
            this.name = name;
    }

    public String toString() {
        return super.toString()+" container carrier with "+teu+" TEU";
    }

}
0
WoeIs 20 nov. 2018 à 22:23

4 réponses

Meilleure réponse

Vous avez déclaré name comme static, ce qui signifie qu'il n'y a qu'une seule copie partagée entre toutes les instances de la classe. Vous souhaitez supprimer le mot-clé static, puis dans vos getters et setters, utilisez le this mot-clé, qui fait référence à l'objet sur lequel la méthode est appelée:

 public void setName(String name) {
    this.name = name;
}

Dans ce cas, la méthode setName sera la même dans les deux classes et vous n'aurez pas besoin de la remplacer dans la sous-classe


Le premier problème avec votre code mis à jour est que vous ne pouvez pas faire référence à une méthode d'instance lors de l'appel explicite d'un constructeur. Au lieu d'appeler getName(), passez l'argument String que vous passez au constructeur:

public SubClass(String string, int length, int teu) {
    super(string, length);
    this.teu = teu;
}

Ensuite, dans votre méthode getName(), vous la traitez comme un setter. Vous devriez plutôt renvoyer le champ name:

public String getName() {
    return this.name;
}

Cela conduit à votre dernier problème: vous utilisez la copie de superclasse de name. Parce que vous l'avez marqué comme privé, il ne sera pas accessible aux autres classes. Vous pouvez soit donner à ContainerShip sa propre variable name, soit rendre le name dans Ship protégé, ou utiliser à nouveau super comme:

public void setName(String name) {
    super.setName(name);
} 
3
GBlodgett 20 nov. 2018 à 19:57

Vous ne pouvez pas accéder aux variables d'instance à partir de méthodes statiques,

private String name="";
private int length=0;

Ce sont des variables d'instance, où votre méthode est déclarée comme static

public static String getName() {

Une chose essentielle à garder à l'esprit lors de la mise en œuvre de l ' héritage .

N'utilisez pas de mot statique avec une déclaration de variable ou n'utilisez pas de mot statique dans la déclaration de méthode.

L'héritage ne se produit que lorsque nous traitons tout avec des variables d'instance et des méthodes d'instance (non statiques). Vous devrez donc changer deux choses,

Change ça,

public static String getName() {

À,

public String getName() {

De même, vous ne pouvez pas accéder aux variables d'instance avec le nom de classe et pour faire référence à l'objet actuel, vous pouvez utiliser this. D'où le changement,

public void setName(String name) {
    Ship.name = name;
}

À

public void setName(String name) {
    this.name = name;
}

De plus, dans ce constructeur, vous avez un problème,

public ContainerShip(String string, int length, int teu) {
    super(getName(), length);
    this.teu = teu;
}

Vous n'utilisez pas la variable string qui est votre premier paramètre. Vous devez changer cette super classe à partir de cela,

super(getName(), length);

À,

super(string, length);

De cette façon, tout ce qui a été passé au constructeur sera transmis au constructeur de la super classe.

Vous devez d'abord résoudre ces problèmes.

De plus, une fois que vous avez créé un objet en utilisant la classe ContainerShip, il aura accès aux méthodes getter / setter de la classe parent Ship car votre sous-classe héritera de ces méthodes qui s'appellent l'héritage. C'est un vaste sujet et au fur et à mesure que vous avancez, vous en saurez plus sur ces constructions. Faites-moi savoir si vous avez d'autres questions concernant l'héritage.

Comme vous avez déclaré vos variables d'instance dans la super classe comme private, vos variables d'instance ne sont pas visibles directement pour les sous-classes, et uniquement disponibles via public getter / setter, mais si vous souhaitez y accéder directement, vous pouvez les déclarer comme protégés et y accéder directement. L'héritage est la raison pour laquelle vous pouvez accéder aux variables de la super classe dans la sous-classe à condition qu'elles ne soient pas déclarées comme privées. Private signifie accessible uniquement dans sa propre classe.

1
Pushpesh Kumar Rajwanshi 20 nov. 2018 à 19:45

Vous pouvez utiliser des interfaces pour définir des classes Type et Abstract afin de définir le comportement par défaut. Par exemple:

interface Ship {
    String getName();
    void setName();
}

abstract class DefaultShip implements Ship {
    private int length;

    public DefaultShip(int length) {
        this.length = length;
    }

    public String toString() {
        return " Ship " + getName() + " l=" + this.length;
    }
}

public class ContainerShip extends DefaultShip {

    private int teu;
    private String name;

    public ContainerShip(String name, int length, int teu) {
        super(length);
        this.name = name;
        this.teu = teu;
    }

    public void getName(String name) {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return super.toString() +" container carrier with " + this.teu + " TEU";
    }
}
0
elbraulio 20 nov. 2018 à 19:49

Vous n'avez pas besoin de setters et de getters dans la sous-classe pour les valeurs de nom et de longueur. Seulement si vous souhaitez les remplacer.

Navire superclasse

public class Ship {

    private String name;
    private int length;

    public Ship(String name, int length) {
        this.name = name;
        this.length = length;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return " Ship "+name+" l="+ length ;
    }

}

Sous-classe ContainerShip

public class ContainerShip extends Ship {

    private int teu;

    public ContainerShip(String string, int length, int teu) {
        super(string, length);
        this.teu = teu;
    }

    public String toString() {
        return super.toString()+" container carrier with "+teu+" TEU";
    }

}

Méthode principale

public static void main(String[] args) {

        ContainerShip cont = new ContainerShip("Name", 100, 4);
        System.out.println(cont.getName());
        cont.setName("new name");
        System.out.println(cont.getName());
}

SORTIE:

Nom

nouveau nom

0
oskozach 20 nov. 2018 à 19:50