2010-07-18 2 views
2

Disons que j'ai un objet de la classe Car, avec comme 30 variables allant de la vitesse maximale à la couleur. Je veux faire un objet MyCar (la classe MyCar étend Car) qui est fondamentalement la même chose sauf qu'il stocke plus d'informations.Étendre objet et hériter toutes les variables

Il m'est impossible de créer des objets MyCar tout de suite (puisque des milliers d'objets Car, seuls quelques-uns deviendront des objets MyCar), à moins de laisser les champs vides, mais cela ne semble pas trop professionnel. Et ne crée pas non plus un constructeur qui prend 30 arguments, ou met 30 arguments à travers des appels de méthode.

Alors, est-il possible d'hériter facilement de toutes les variables d'un objet de super-classe? PS: Mon programme ne concerne pas les voitures, mais je pensais que ce serait un exemple plus facile.

EDIT

Merci pour les réponses. Ils sont tous utiles pour mon programme, mais pas pour ce problème particulier. Les constructeurs ne semblent pas bénéfiques parce que mes voitures n'ont pas de valeurs par défaut pour leurs variables. Chaque fois qu'une voiture est faite, toutes les variables sont remplies (ce qui est nécessaire pour construire une sorte de «fiche d'information»).

Les enveloppes sont une conception intéressante, mais nécessitent encore que je copie toutes les variables dans le constructeur de la sous-classe. J'espérais qu'il y aurait un moyen de contourner cela. Les modèles nécessiteraient également que je copie toutes les variables une par une.

Dans mon programme, la sous-classe agit comme une sorte de «classe wrapper» dans un moteur de recherche. Les sous-classes sont les mêmes que les voitures normales, mais elles ont un «score de classement». Mon programme est conçu pour afficher les voitures ordinaires, et en prolongeant ceux que je peux facilement afficher les sous-classes et les ordonner par score en même temps.

Je dois quand même créer de nouveaux objets, car plusieurs recherches peuvent être effectuées sur la même liste de voitures. Donc modifier les variables dans les voitures d'origine n'était pas une option.

Peut-être qu'il existe une meilleure solution à ce problème, mais pour l'instant je suppose que je vais devoir passer l'objet superclasse dans le constructeur et copier toutes les variables là-bas.

Merci pour l'aide! PS: Je pense juste, peut-être que je pourrais jeter toutes les variables dans un HashMap. De cette façon, je pourrais y accéder en utilisant .get (varname), et je n'aurais qu'à passer une variable HashMap dans la sous-classe. L'inconvénient est que je devrais jouer beaucoup, car les vars sont un mélange de cordes, d'ints, de doubles, etc. Que pensez-vous, est-ce un style de codage acceptable?

Répondre

1

Vous pouvez ajouter un constructeur qui obtient un objet Car et copier les valeurs de Car dans le nouveau MyCar.

4

Effective Java 2e édition, article 2: Considérons un constructeur face à de nombreux paramètres constructeur

Et ni le fait de créer un constructeur qui prend 30 arguments, ou réglage de 30 arguments par la méthode appels .

Si vous êtes face à un constructeur avec trop de paramètres alors vous voudrez peut-être jeter un oeil à: Le Builder Pattern. L'idée est de définir que le champ que vous voulez/savoir dans le générateur , sans se soucier des optionnelles, ou ceux que vous voudriez utiliser valeurs par défaut, puis en appelant build() pour construire l'objet réel . Voir les exemples Java dans cet article.

Une fois que vous avez configuré ce modèle, vous pouvez construire voitures de cette façon (remarquez la structure propre):

Car car = new Car.Builder(required_param1, required_param2) 
       .color(RED) // optional params 
       .topSpeed(300) 
       .zeroToHundred(2) 
       .build(); 
+0

FYI, l'équation .NET est d'utiliser les propriétés pour définir tous les paramètres facultatifs (et parfois requis - vous obtenez IllegalStateException jusqu'à ce que vous le fassiez). – Joshua

1

Il est impossible pour moi de créer MyCar objets tout de suite (depuis de milliers des objets Car seulement quelques-uns deviendront des objets MonAuto),

Ainsi, vous aurez beaucoup d'objets de type de voiture, dont quelques-uns que vous souhaitez, lors de l'exécution, « promouvoir » le type SpecialCar ?

Est-ce que SpecialCars ont exactement la même interface que Cars?

Vous voudrez peut-être lire sur Envelope-Letter Pattern de Coplien, c'est une façon de "changer" le type d'objet à l'exécution. L'objet ne change pas vraiment de type, bien sûr; au lieu de cela, une "lettre" différente entre dans "l'enveloppe" existante. L'enveloppe est la poignée que d'autres références de code, mais la méthode invite l'enveloppe sont déléguées à la lettre:

class CarEnvelope { // an envelope 
    Car c ; // the letter 
    CarEnvelope(Car c) { this.c = c ; } 
    int someMethod() { 
     return c.someMethod(); // delegate 
    } 
    void promoteToSpecialType() { 
     if(! c.isSpecialCar()) { 
      c = new SpecialCar(c) ; 
    } 
} 

class Car { 
    Car() {} 
    int someMethod() { do Car stuff } 
    boolean isSpecial() { return false; } 
} 

class SpecialCar extends Car { 
    SpecialCar(Car c) { /*copy c's attributes...*/ } 
    int someMethod() { do SpecialCar stuff} 
    boolean isSpecial() { return true; } 
} 

CarEnvelope c = new CarEnvelope(new Car()) ; 
// do stuff with c 
c.someMethod(); // indirectly calls Car.someMethod(); 
// promote 
c.promoteToSpecialType(); 
c.someMethod(); // indirectly calls SpecialCar.someMethod 
0

J'ai le sentiment que ce que vous recherchez est la notion d'un modèle; par exemple.

public class Car { 
    private final int attr1; 
    private final int attr2; 
    ... 

    public Car() { 
     super(); 
    } 

    /* copy constructor */ 
    public Car(Car template) { 
     this.attr1 = template.attr1; 
     this.attr2 = template.attr2; 
     ... 
    } 

    /* setters and getters */ 
} 

Alors ...

Car myTemplate = new Car(); 
myTemplate.setAttr1(3); 
myTemplate.setAttr2(11); 
... 

Car car1 = new Car(myTemplate); 
car1.setAttr1(4); 
Car car2 = new Car(myTemplate); 
car1.setAttr1(5); 
0

OP ici. Je comprends que cela ressemble à de la paresse. Mais je l'ai déjà en travaillant en copiant manuellement 30 variables dans le constructeur. Pas si gros que ça, je sais.

La chose est, j'ai appris à coder avec style. Quand je vois des blocs de code stupides qui ressemblent à du copypasta, mes instincts me disent qu'il y a probablement un meilleur moyen. Donc, mon désir d'apprendre et d'aspirer à la perfection m'a conduit ici.

Mais s'il n'y a vraiment pas d'autre moyen que de copier les variables (ou de surcharger toutes les méthodes set get &) alors je n'ai pas besoin de regarder plus loin.

Inutile de dire que toutes les réponses à ce sujet m'ont donné de nouvelles idées. Merci les gars.

0

Je ne comprends pas. Quel est le problème avec un héritage régulier?

class Car { 
    private int attributeOne; 
    ..... 
    private boolean attrbuteThirty; 

    public void methodOne(){...} 
    ... 
    public void methodThirty(){...} 
} 

Et puis la sous-classe juste:

class SubCar extends Car { 
    private int extraAttribute; 
    } 

Tous les attributs et les méthodes de 30 sont déjà hérité, c'est ce que l'extends est tout au sujet.

Si ce que vous avez besoin est de créer un nouveau objet sur la base des données d'un existant, mais vous résister à le code it! (¬¬), alors vous pouvez simplement créer un petit script pour créer le code pour vous. C'est très facile. Vous copiez/collez le code généré et vous avez terminé.

Si vous ne voulez pas le faire, parce que vous ne voulez pas dupliquer les données, vous pouvez remplacer les méthodes intéressantes et déléguer le code à l'original, c'est ce que le Decorator design pattern est tout au sujet:

class SubCar extends Car { 
    private Car wrapped; 
    private String extraAttribute; 
    public SubCar(Car original, String newAttributeOne) { 
     wrapped = original; 
     this.extraAttribute = newAttributeOne; 
    } 

    public void someMethod() { 
     wrapped.someMethod(); 
    } 
    public String getName() { return wrapped.getName(); } 
    ... and so on 
    // new method 
    public String extraAttribute() { return extraAttribute; } 
} 

De cette façon, vous ne dupliquerez pas les données, mais simplement les décorer.

0

Nous pouvons créer une interface ICar qui a tous les getters et les setters pour toutes les 30 colonnes. Car peut implémenter ICar et peut contenir tous les 30 champs avec leurs getters et setters correspondants. MyCar peut également implémenter ICar et peut utiliser la composition. Il expose les méthodes de voitures que les méthodes de délégués (qui peuvent automatiquement être générés dans un IDE comme Eclipse)

public interface ICar { 
// getter and setter methods 
} 

public Car implements ICar { 
private String color; 
// getters and setters for each of the fields 
} 

public MyCar implements ICar { 
private Car car; 
public MyCar(Car car){ 
    this.car = car; 
} 
public String getColor() { 
    return car.getColor(); 
} 
} 

Tous les consommateurs pourraient alors utiliser l'interface ICAR pour leur manipulation. Ça marchera?