3 Replies - 307 Views - Last Post: 28 February 2019 - 11:13 AM

#1 MentalFloss   User is offline

  • .
  • member icon

Reputation: 619
  • View blog
  • Posts: 1,588
  • Joined: 02-September 09

Accuracy/Efficacy of Class Diagram

Posted 28 February 2019 - 05:54 AM

In lecture today, I was presented with a very strange class diagram that managed to throw my intuition about OOP into turmoil, and I was hoping that you guys could think about this with me.

Consider the diagram:

Posted Image

Note that ActionCharacter does implement CanFly interface, and since Hero extends from ActionCharacter, which has a method of that type, this is acceptable.

However, I am wondering if this is actually the correct thing to do because it seems to violate Liskov's substitution principle in that subtypes must be able to be substituted wherever supertypes are used without changing behavior.

In the standard case, this seems to be a vacuously true statement as ActionCharacter would be unable to be passed to some method with a signature of method(CanFly flier). However, we are presuming ActionCharacter be be a flier already because of the fly() method. What this means is that ActionCharacter is rejected from this method, but Hero is not.

The only way I see this being a viable implementation is if ActionCharacter were abstract. Then it would not be instantiated in the first place, and there would be no problem. However, since I could create an ActionCharacter, it would not benefit from obeying the CanFly interface even though it seems like it is intended to.

Ultimately, I want to know if this is correct. I also want to know (if correct) what the benefits of this is. Does it decouple more effectively? Should I be considering it in my own projects? Or is this in error, and I'm right to consider this a bad relationship?

Thank you for checking into this, and thinking about (what I consider to be) a strange problem.

Is This A Good Question/Topic? 0
  • +

Replies To: Accuracy/Efficacy of Class Diagram

#2 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6767
  • View blog
  • Posts: 23,071
  • Joined: 05-May 12

Re: Accuracy/Efficacy of Class Diagram

Posted 28 February 2019 - 06:19 AM

I think that the solid vs. dashed lines for inheritance in that diagram are significant. I suspect that dashed lines are MAYBE-A relationship as opposed to the solid line IS-A relationship.
Was This Post Helpful? 0
  • +
  • -

#3 MentalFloss   User is offline

  • .
  • member icon

Reputation: 619
  • View blog
  • Posts: 1,588
  • Joined: 02-September 09

Re: Accuracy/Efficacy of Class Diagram

Posted 28 February 2019 - 06:34 AM

Dashed lines are a generalization. So, we're saying that Hero implements the interfaces CanFly, CanFight, CanSwim.
Was This Post Helpful? 0
  • +
  • -

#4 Martyr2   User is online

  • Programming Theoretician
  • member icon

Reputation: 5360
  • View blog
  • Posts: 14,258
  • Joined: 18-April 07

Re: Accuracy/Efficacy of Class Diagram

Posted 28 February 2019 - 11:13 AM

MentalFloss is correct. That is for a "required" interface.

Now a few comments that the original poster brought up...

1) According to the diagram, no ActionCharacter does not implement the CanFly interface. It just has a method called Fly(). Now I understand you might mean class interface in the generic sense of the word, but just clarifying since it does not in fact implement the CanFly <<interface>> according to the diagram.

2) No, this is not going to violate the Liskov substitution principle. Can Hero do everything that ActionCharacter can? Yes, it implements a fly method. Period. Doesn't matter if it is abstract or not. All that needs to be satisfied is that Hero implements everything its base class can do. We know this because if it doesn't it violates the interface contract as well. Meaning that we could treat Hero as an ActionCharacter and have no issues.

3) Not sure what you mean by ActionCharacter can't be passed to a method but Hero can. Again, Hero can be used in place of ActionCharacter. The only thing that can't be done is passing an ActionCharacter to a method expecting a Hero because ActionCharacter does not implement other methods that a Hero does. Hero is a specialized instance of ActionCharacter.

4) I am not sure why you think this is a bad relationship setup. This is perfectly valid. You might have methods in ActionCharacter that isn't covered by an interface. Don't let the fact that Fly() is implemented in an interface confuse you. All an interface does is establish a "contract of understanding". If a class implements the interface we are being told contractually that the class implements that method and we can rely on it. Otherwise we should get a hard error because we did something wrong and violated that promise.

I hope this helps the understanding. :)

P.S. Also consider how you might introduce a "non-hero" ActionCharacter. It might not have any of the abilities of canswim, canfight.... but maybe they can fly. They could inherit from the ActionCharacter but not implement any of the interfaces that Hero does.

This post has been edited by Martyr2: 28 February 2019 - 11:18 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1