2

Is it possible and does it make sense that Hero has an aggregation and composition relationship?

My aim is to keep a list of powers for each hero, however when creating one it should only be possible to add one Power instead of multiple Powers. That is the reason why I've created a private attribute power for only one power.

My question is about the validity of the UML class diagram. Is that the correct way of displaying my intend?

The reason why power is an aggregation is that it could be that another class uses the same power instance (I have implemented some cache which always return the same instance of a power, for simplicity I didn't show that part).

The reason why powers is an composition is that it strongly depends on the hero instance. If hero is destroyed, powers should also be cleaned.

Hero UML Composition, Aggregation

The code for the UML does look like something like that (TypeScript):

hero.ts

import { Power } from './power';

export class Hero {
  powers: Power[] = [];

  constructor(private power?: Power) {
    if (power) {
      this.addPower(power);
    }
  }

  addPower(power: Power) {
    this.powers.push(power);
  }

}

power.ts

export class Power {
  constructor(private title: string) { }
}
Kevin Olomu
  • 702
  • 1
  • 6
  • 19
  • See my answer at https://stackoverflow.com/questions/48268986/is-correct-relatshass-digram-crrel though the OP there is trolling at the moment :-/ – qwerty_so Jan 18 '18 at 08:47
  • Your list of Power is it fixed for all Heros or each Hero will have acces to a different set of Power? – Red Beard Jan 18 '18 at 08:50
  • Hi, @1 so you say that I should better use association with multiplicities instead of aggregation and composition? @2 each Hero should have a different set of Powers – Kevin Olomu Jan 18 '18 at 08:56
  • 1
    Yes, multiplicity is in almost all cases the better choice. And it saves a lot of headaches. – qwerty_so Jan 18 '18 at 09:37
  • 1
    Rather than editing your question with the answer you should post that as a new "answer to self". That would be perfect. – qwerty_so Jan 18 '18 at 10:09

2 Answers2

2

First of all: it is possible to have an Aggregation and Composition between two classes. As you said correctly, if our part class should be deleted with whole class, we should use Composition, and if not, we can use Aggregation (or Association). It is possible to have both in one direction (as you have, only the recursive relation is not possible)

Based on you explanation:

My aim is to keep a list of powers for each hero, however when creating one it should only be possible to add one Power instead of multiple Powers. That is the reason why i've created a private attribute power for only one power.

You do not have Aggregation between Hero and Power. That is only a Dependency relationship between them. Based on your codes and explanation, you do not save the ONE power in your codes and only it used for setting instances to POWERS in Hero. Meaning that your Hero has not any single Power as part class.


However, your Composition between them is absolutely correct. Because you said:

it strongly depends on the hero instance. If hero is destroyed, powers should also be cleaned.

Gholamali Irani
  • 4,391
  • 6
  • 28
  • 59
  • Hi, thanks for your detailed answer. I think I have an Aggregation because I save one power at the initialization of one instance. If the constructor in typescript contains something with a modifier and a type, typescript will initialize the value. E.g. writing constructor(private power: Power) resolves to this: export class Hero { powers: Power[] = []; power: Power; constructor(power?: Power) { if (power) { this.power = power; this.addPower(power); } } or is it something else that you mean? – Kevin Olomu Jan 18 '18 at 09:04
  • 1
    I think, the `power` that generated at initialization, is something like a temporary variable to handle your codes. We use Aggregation because of Structural reasons. – Gholamali Irani Jan 18 '18 at 09:12
2

Solution based on accepted answer in UML: enter image description here

In TypeScript it's better to not instantiate a attribut of type Power because it has no further purpose. Therefore the constructor just get a Power and is adding it to the powers array.

hero.ts

import { Power } from './power';

export class Hero {
  powers: Power[] = [];

  constructor(power?: Power) {
    if (power) {
      this.addPower(power);
    }
  }

  addPower(power: Power) {
    this.powers.push(power);
  }

}
Kevin Olomu
  • 702
  • 1
  • 6
  • 19