Giter Site home page Giter Site logo

Comments (10)

Penaz91 avatar Penaz91 commented on June 7, 2024

That is actually not a typo, my intention was showing that the PlayableCharacter class ties to the interface Updatable which in turn finds the necessary implementation in MovableObject (like Building ties to Updatable too, but will find its implementation in ImmovableObject).

Your hunch is not wrong though, you can make a more "restrictive" interface that handles only movement called Moveable, instead of the more generic (handles generic internal state updates) Updatable.

This is one of those situations where I can't explain well something without explaining another, and I can't explain that other thing without first explaining the first. The case is UML and Object Oriented programming.

The members of the package "Implementations" realize the interfaces of the "Interfaces Package" (this is "said" by the dashed arrows with a empty triangle head), while the members of the "Objects" package are merely "dependent" on the interfaces (as "said" by the simple dashed arrows).

Thus there is a Interface->Implementation relationship (or a Parent->Child class relationship for languages that don't use interfaces) between MovableObject and Updatable, for instance.

Hopefully I managed to explain this well!

from 2dgd_f0th.

abreathingcorpse avatar abreathingcorpse commented on June 7, 2024

That is actually not a typo, my intention was showing that the PlayableCharacter class ties to the interface Updatable which in turn finds the necessary implementation in MovableObject (like Building ties to Updatable too, but will find its implementation in ImmovableObject).

I could have sworn that the Building Object had:
movablecomponent: Immovable;

Guess that reading before bedtime can have its issues, like writing too late. Sorry about the false bug.

This is one of those situations where I can't explain well something without explaining another, and I can't explain that other thing without first explaining the first. The case is UML and Object Oriented programming.

I'll keep on reading and see if it makes more sense later.
Because right now I understand that PlayableCharacter will have 3 pure virtual functions: update(), draw() & collide().

I guess that if we have a MovableObject as a child of PlayableCharacter it may overwrite the update() method. On a similar way, VisibleObject and CollidableObject could overwrite the draw() & collide() methods.

Please, let me know if my understanding of what Interfaces are is wrong.

from 2dgd_f0th.

Penaz91 avatar Penaz91 commented on June 7, 2024

I could have sworn that the Building Object had:
movablecomponent: Immovable;

It's in the notes, so you're not wrong. It just happens that Immovable is one possible realization of the "Updatable" interface.

Interfaces are a "contract" that a certain class (implementing such interface) must respect: in essence the implementing class must have certain functions declared and written. They have a lot in common with abstract classes.

Think of the following case: you have an interface with 3 methods: "seek", "read", "write". Such interface could be implemented by a "DiskFile" class, as well as by a "MemoryFile" one. By hooking to the interface, you don't need to care if the file is on disk on in memory, you just need those 3 methods to be able to "deal with them" properly. With a proper driver under the hood you could be using a "TapeFile" class (which saves on Ultrium tapes) and still be able to use the same methods in your user code (outside of the TapeFile class, obviously).

Because right now I understand that PlayableCharacter will have 3 pure virtual functions: update(), draw() & collide().

I guess that if we have a MovableObject as a child of PlayableCharacter it may overwrite the update() method. On a similar way, VisibleObject and CollidableObject could overwrite the draw() & collide() methods.

If multiple inheritance is used to implement PlayableCharacter, it means that PlayableCharacter will be a child of MovableObject (because MovableObject will implement a more "generic behaviour"). If components are involved things will be a bit easier, since a variable will contain an instance of "MovableComponent" and the "update()" method will just do movablecomponent.update() as well as some ancillary operations, if necessary.

As a small pointer on (and preview of) UML, when Interface realization and Subclassing is involved, the tip of the arrow points to the "parent class". Hopefully this makes things a bit clearer.

from 2dgd_f0th.

abreathingcorpse avatar abreathingcorpse commented on June 7, 2024

I think I understand the basics of Composition now.
Please, correct me if I'm wrong.

In C++ you would have a pure virtual function for the update() method within the Updatable class.
Then, the Movable component will need to implement said method.
The PlayableCharacter class would be a child of the Updatable Interface and either create its own update() implementation or call the one from MovableObject.
Did I understand it right?

from 2dgd_f0th.

Penaz91 avatar Penaz91 commented on June 7, 2024

The PlayableCharacter class would be a child of the Updatable Interface and either create its own update() implementation or call the one from MovableObject.

Composition-driven design pushes for HAS-A relationships. This means that PlayableCharacter will have a field that is compatible with the Updatable interface (so in our case it would be an instance of the "MovableObject" class). Then PlayableCharacter will have to implement its own update() method (because we decided that PlayableCharacter needs one) that uses the one from its MovableObject instance (and it either just does that or does some ancillary work).

This comes particularly useful if we want the update method to do many things, like movement and collision checking. In that case you'll have 2 fields: one for MovableObject and one for CollidableObject. Then PlayerCharacter's update() function could look something like this:

class PlayableCharacter{
    ...
    Updatable movement_component = MovableObject();
    Updatable collision_component = CollidableObject();
    ...
    void update(float dt){
        ....
        movement_component.update();
        collision_component.collide();
    }
}

This is a very abstract example, but hopefully it clears things up a bit.

from 2dgd_f0th.

abreathingcorpse avatar abreathingcorpse commented on June 7, 2024

Composition-driven design pushes for HAS-A relationships. This means that PlayableCharacter will have a field that is compatible with the Updatable interface

Right, because PlayableCharacter has a dependency on the Updatable interface, but it does not have a realization relationship like the MovableObject does.


Updatable movement_component = MovableObject();

I'm sorry but, this still confuses me a bit. I understand that MovableObject is a class which implements the update() pure virtual function from the Updatable interface.
When we say that the PlayableCharacter HAS-A Updatable Interface, do we mean literally? Or that the PlayableCharacter has a MovableObject instance with an update() method?

How can we assign a Constructor of a class to an instance of its interface?
Perhaps this is written in Pseudocode and I'm confusing it with C++?

In C++ I believe this should be done like this:

private:
    MovableObject movement_component;

Updatable collision_component = CollidableObject();

Also, this should be Collidable collision_component = CollidableObject();, right?

from 2dgd_f0th.

Penaz91 avatar Penaz91 commented on June 7, 2024

I'm sorry but, this still confuses me a bit. I understand that MovableObject is a class which implements the update() pure virtual function from the Updatable interface.

In case of C++, there are no interfaces but you can use Abstract classes. In that case you can have an "Updatable" abstract class which finds implementation in MovableObject. Since you can assign a subclass to a variable that has a "superclass" type what I wrote is valid, just more generic (that also means that I can only use the functionalities declared in "Updatable").

Since we declared update() as virtual, the subclass's method will be always called.

When we say that the PlayableCharacter HAS-A Updatable Interface, do we mean literally? Or that the PlayableCharacter has a MovableObject instance with an update() method?

Yes, there will be a variable inside of PlayableCharacter that is an instance of MovableObject. In that case a more fitting name for the class would be something like "MovementController" or "MovementComponent"

How can we assign a Constructor of a class to an instance of its interface?

As I said above, when it comes to Abstract classes, you can because you're assigning a subclass to a superclass (it's a bit like putting a "circles" and "squares" in a box that says "shapes": it is correct).

In languages that use interfaces, it's a similar concept. An example could be Java's "Set" interface (as a container containing only one instance of a certain element): you can have a variable ask for a "Set", but assign a HashSet or a TreeSet (since they both implement the functionalities required by the "Set" interface). Back to the "Shape" example, you could have a variable requiring "something you can calculate the area of", and assign a "circle" or a "square" as long as those classes (which realize the interface) have some kind of "calculateArea()" method.


Also, this should be Collidable collision_component = CollidableObject();, right?

Yes, I mixed them up, due to the fact that I'm used to check for collisions in the update() function. Apologies.

Hopefully I didn't make things even more confusing. Feel free to ask all the question you want!

from 2dgd_f0th.

abreathingcorpse avatar abreathingcorpse commented on June 7, 2024

In that case you can have an "Updatable" abstract class which finds implementation in MovableObject. Since you can assign a subclass to a variable that has a "superclass" type what I wrote is valid, just more generic (that also means that I can only use the functionalities declared in "Updatable").
Since we declared update() as virtual, the subclass's method will be always called.

This is really interesting.

However, the compiler did not like it when I wrote it like this:

Updatable movement_component = MovableObject();

I got the following error:

...
error: cannot declare field ‘PlayableCharacter::movement_component’ to be of abstract type ‘Updateable’
...
error: cannot allocate an object of abstract type ‘Updateable’
28 | Updateable movement_component = MovableObject();

I got in touch with a professor and he suggested that I do it the following way:
Updateable* movement_componen = new MovableObject();

Then we can call this within the update method of the PlayableCharacter class like so:
movement_component->update();

Let me know your thoughts : ]

from 2dgd_f0th.

Penaz91 avatar Penaz91 commented on June 7, 2024

I got in touch with a professor and he suggested that I do it the following way:
Updateable* movement_componen = new MovableObject();
Then we can call this within the update method of the PlayableCharacter class like so:
movement_component->update();
Let me know your thoughts : ]

That is indeed the correct solution. we cannot directly work with abstract classes (due to obviously non-implemented methods) but using pointers and virtual methods (which makes the program call the method of the derivative class) we can sidestep the issue.

I haven't seriously coded in C++ in years, so my memory is still quite foggy ^^'

from 2dgd_f0th.

abreathingcorpse avatar abreathingcorpse commented on June 7, 2024

I haven't seriously coded in C++ in years, so my memory is still quite foggy ^^'

That's okey. I like to think that by writing the solution you also get a reminder of how things work on this specific language.

from 2dgd_f0th.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.