Inheritance with composition - c++

I am designing a system, I have not yet implemented first I am just diagraming it and then will code it, I want to ask one simple question:
What to do when we are using both inheritance and composition at the same time?
For example, in a hotel, there are 2 kinds of room standard room and Twin room let us say. For this I can use inheritance concept and these 2 kinds of rooms will be derived class but i can also use composition and will make seperate class for standard and twin room, then will use this is my hotel class.
What should I do?

This question is kinda vague and there are many details missing, yet I'll share some ideas...
First thing: while working on design of your application, what matters the most are the requirements.
You need to try to identify entities that will have some meaning in your system first. Let's say you know that there will be Hotel and Room. Note, that this relation is a composition already, mainly because:
room can be part of only 1 hotel, it is not shared among multiple hotels
once the hotel is destroyed, so are all rooms in it
in C++, composition usually means "by value", i.e. class Hotel could have Room room; that would be an object with automatic storage duration with its lifetime tied to the lifetime of instance of Hotel, with multiple rooms you could just put them to the vector yielding the same relationship:
class Room { ... };
class Hotel {
public:
std::vector<Room> rooms;
};
(By the way, an aggregation would be most likely represented by a pointer or reference). This is another good example of composition:
If you know that there will be different kinds of rooms, first questions should be: will these objects have different behaviour? will my system treat them in different way? ...maybe you don't need to go for finer granularity than Room and everything that a concrete room will be specific with will be expressed with its attributes - size, number of beds, maybe dozens of boolean "has" flags ("has aircon", "has TV", "has microwave", ...), maybe all of its properties can be expressed with simple "type", values of which you would put into the enum.

I the case you site, I would have a room_type property on the room class, and I would set the type of the room_type property to an enumerated type with possible values of STANDARD and TWIN.
As long as there are not significant behavioral differences depending upon this type field, I would keep it simple.
If there are complicated behaviors, like predicting clean up based upon number of beds, changing pricing, and so on, I would use an abstract base class CRoom, and inherit CStdRoom and CTwinRoom from that, possibly setting a constant num_of_beds property in the class constructors.

You shouldn't use language inheritance to model business requirement inheritance. It just makes it too hard to modify or extend the business model. Language inheritance is for implementing features of your model, not the model itself.
Instead, derive all your objects from 'business object' or similar, to encapsulate common internal behaviour such as serialisation. Your classes can have types and you can use typeinfo, or you can use an explicit type field. Either way links between objects, whether inheritance-like or composition-like should be pointers (or index id fields) and collections (of pointers or index ids). [Your code snippet is fine, but pointers complicate memory management which integer ids avoid.]
Complicated behaviours should belong to other classes such as the Pricing, Cleaning, etc. There are other patterns to use in setting the relationships between business objects and business actions, but again avoid crystallising them using language features. You will regret it, if the system grows or changes even a bit.

Related

A question about encapsulation and inheritence practices

I've heard people saying that having protected members kind of breaks the point of encapsulation and is not the best practice, one should design the program such that derived classes will not need to have access to private base class members.
An example situation
Now, imagine the following scenario, a simple 8bit game, we have bunch of different objects, such as, regular boxes act as obstacles, spikes, coins, moving platforms etc. List can go on.
All of them have x and y coordinates, a rectangle that specifies size of the object, and collision box, and a texture. Also they can share functions like setting position, rendering, loading the texture, checking for collision etc.
But some of them also need to modify base members, e.g. boxes can be pushed around so they might need a move function, some objects may be moving by themselves or maybe some blocks change texture in-game.
Therefore a base class like object can really come in handy, but that would either require ton of getters - setters or having private members to be protected instead. Either way, compromises encapsulation.
Given the anecdotal context, which would be a better practice:
1. Have a common base class with shared functions and members, declared as protected. Be able to use common functions, pass the reference of base class to non-member functions which only needs to access shared properties. But compromise encapsulation.
2. Have a separate class for each, declare the member variables as private and don't compromise encapsulation.
3. A better way that I couldn't have thought.
I don't think encapsulation is highly vital and probably way to go for that anecdote would be just having protected members, but my goal with this question is writing a well practiced, standard code, rather than solving that specific problem.
Thanks in advance.
First off, I'm going to start by saying there is not a one-size fits all answer to design. Different problems require different solutions; however there are design patterns that often may be more maintainable over time than others.
Indeed, a lot of suggestions for design make them better in a team environment -- but good practices are also useful for solo projects as well so that it can be easier to understand and change in the future.
Sometimes the person who needs to understand your code will be you, a year from now -- so keep that in mind😊
I've heard people saying that having protected members kind of breaks the point of encapsulation
Like any tool, it can be misused; but there is nothing about protected access that inherently breaks encapsulation.
What defines the encapsulation of your object is the intended projected API surface area. Sometimes, that protected member is logically part of the surface-area -- and this is perfectly valid.
If misused, protected members can give clients access to mutable members that may break a class's intended invariants -- which would be bad. An example of this would be if you were able to derive a class exposing a rectangle, and were able to set the width/height to a negative value. Functions in the base class, such as compute_area could suddenly yield wrong values -- and cause cascading failures that should otherwise have been guarded against by better encapsulated.
As for the design of your example in question:
Base classes are not necessarily a bad thing, but can easily be overused and can lead to "god" classes that unintentionally expose too much functionality in an effort to share logic. Over time this can become a maintenance burden and just an overall confusing mess.
Your example sounds better suited to composition, with some smaller interfaces:
Things like a point and a vector type would be base-types to produce higher-order compositions like rectangle.
This could then be composed together to create a model which handles general (logical) objects in 2D space that have collision.
intersection/collision logic can be handled from an outside utility class
Rendering can be handled from a renderable interface, where any class that needs to render extends from this interface.
intersection handling logic can be handled by an intersectable interface, which determines behaviors of an object on intersection (this effectively abstracts each of the game objects into raw behaviors)
etc
encapsulation is not a security thing, its a neatness thing (and hence a supportability, readability ..). you have to assume that people deriving classes are basically sensible. They are after all writing programs either of their own using your base classes (so who cares), or they are writing in a team with you
The primary purpose of "encapsulation" in object-oriented programming is to limit direct access to data in order to minimize dependencies, and where dependencies must exist, to express those in terms of functions not data.
This is ties in with Design by Contract where you allow "public" access to certain functions and reserve the right to modify others arbitrarily, at any time, for any reason, even to the point of removing them, by expressing those as "protected".
That is, you could have a game object like:
class Enemy {
public:
int getHealth() const;
}
Where the getHealth() function returns an int value expressing the health. How does it derive this value? It's not for the caller to know or care. Maybe it's byte 9 of a binary packet you just received. Maybe it's a string from a JSON object. It doesn't matter.
Most importantly because it doesn't matter you're free to change how getHealth() works internally without breaking any code that's dependent on it.
However, if you're exposing a public int health property that opens up a whole world of problems. What if that is manipulated incorrectly? What if it's set to an invalid value? How do you trap access to that property being manipulated?
It's much easier when you have setHealth(const int health) where you can do things like:
clamp it to a particular range
trigger an event when it exceeds certain bounds
update a saved game state
transmit an update over the network
hook in other "observers" which might need to know when that value is manipulated
None of those things are easily implemented without encapsulation.
protected is not just a "get off my lawn" thing, it's an important tool to ensure that your implementation is used correctly and as intended.

Class diagram: Can I share a composition?

Let's say I'm using the mvc pattern to make a simple game in c++ and have a world object whose lifetime is managed by a controller class. This feels clearly like a composition, but what if, say a game logic class needs a permanent reference to the same world as well, or environments to this world (who is owned by the world) needs references to it, are these just regular associations or should I make all shared aggregations?
What makes me confused is that composition is defined as 'unshared'. But does this mean not shared with any other relationship, or only not shared with other aggregations and compositions. Also, how is shared aggregation typically implementet in c++? I mean, someone must manage the lifetime. Now we can use shared_ptr, but without them are everything shared just created in main and passed (and destroyd) from there? Which leads me to wonder; is it wrong to model the controller in a class diagram, should only the model part be modelled?
As another example of my main question (are composites allowed to be shared with any other kind of relation in a uml class diagram) e.g. can a wheel on a car be shared with other objects? If the engine needs a permanent reference, how should it be modelled? A simple association?
Yes, it is possible and one of the best example is that of a pool (the struture, not the one with water...). In a pool, the pool manager has a composition relationship with all the elements. The pool manager manages the allocation of elements to "users" as required. The users are now sharing these agregate elements.
It is important to note that the pool manager is the owner of the pool elements and is, therefore, responsible for their creation and destruction (as required to maintain the pool within prescribed limits) and needs to keep track of their allocation. The pool elements can also only have one owner. The pool's user can only borrow and return an element in this scenario.
In your scenario, I would suspect you can use either aggregations or just a simple association, keeping in mind that the owner of the object (the one with the composition) can destroy it...
Taking your car-part of the question, if you mean if it is legal to use both white and black diamonds in the same picture like in this one..
..then I think it is perfectly valid and doable.
In my understanding the black diamonds just represent the "ownership", saying who is responsible for releasing memory and chaining the calls to destructors and invalidating the other weak pointers (those coming from lines with white diamonds and lines without diamonds)
Another picture where both diamonds co-exist at the same time can be found at Kirill Fakhroutdinov's site under..
EDIT: after #gwag comment
http://www.uml-diagrams.org/library-domain-uml-class-diagram-example.html (see the Library class)
..http://www.uml-diagrams.org/dicom-real-world-uml-class-diagram-example.html (see the Visit class)
Your main question ("are composites allowed to be shared with any other kind of relation in a uml class diagram") is not very well expressed. You probably refer to components and not to composites. Indeed, a wheel, as a part/component of a car, cannot be shared with other cars (at the same time), while an employee, as a part of a company or team, can be shared with several other companies or teams..
But this non-shareability concerns only the two classes involved in the composition relationship (Car and Wheel, Company and Employee). And it does not restrict component objects to participate in other relationships instantiating other associations.

Associating types with each other

I have an Action class from which I derive several subtypes. Now, I need to associate some of these subtypes with each other, in a one-to-many relationship. The idea is that some types of Action subtype will make other subtypes available/unavailable (i.e. I also need to create them on the fly). Since in a language like C++ you cannot store type variables the only thing that makes sense is an association of string typenames.
Has anyone met a similar situation? And if so, would you simply use a non-unique associative container like std::multimap and then manually hardcode a huge switch statement for the string-type association?
Example: An action of type Attackwill eventually make Retreat available to its actor, as well as others, like Charge etc. Each action constructor takes at least one Actor reference, but it may also take other, unknown at compile-time, parameters. This last bit makes it very difficult to model this as a decision/action tree... in other words, it seems like I have to build the decision tree during runtime.

C++: Array of parent and child objects

I am designing a game in which some players cards are known and some aren't. To do this, I made a parent object "Player" with children "OpenPlayer" and "ClosedPlayer".
I want to make an array of all the players in this game to facilitate game management. However, I also want to be able to access the special methods in OpenPlayer and ClosedPlayer as appropriate. Is this possible?
Edit: I am actually thinking of using a vector from STL as this would likely be more appropriate due to variable number of players.
In general, you can't make a C++ array whose elements are of different class types; each array element must be the same size, and that won't necessarily be true of different subclasses. Putting different types in the the array can result in slicing, which is the surprising disappearance of the data members of a subclass.
But if you make an array of pointers to your different subclasses, then you'll easily be able to do what you want. You might also consider using a vector instead of an array if the number of players can vary.
By "access special methods" I assume you mean methods in just the OpenPlayer or just the ClosedPlayer?
By array, I assume you mean some STL collection ;-)
The short answer is "No".
The long answer is "Yes you can, but you'll need to cast objects to the correct type. This implies that your design is wrong."
A different disign might be to make "Open" or "Closed" a property of the Player class rather than individual subclasses.

Worth using getters and setters in DTOs? (C++)

I have to write a bunch of DTOs (Data Transfer Objects) - their sole purpose is to transfer data between client app(s) and the server app, so they have a bunch of properties, a serialize function and a deserialize function.
When I've seen DTOs they often have getters and setters, but is their any point for these types of class? I did wonder if I'd ever put validation or do calculations in the methods, but I'm thinking probably not as that seems to go beyond the scope of their purpose.
At the server end, the business layer deals with logic, and in the client the DTOs will just be used in view models (and to send data to the server).
Assuming I'm going about all of this correctly, what do people think?
Thanks!
EDIT: AND if so, would their be any issue with putting the get / set implementation in the class definition? Saves repeating everything in the cpp file...
If you have a class whose explicit purpose is just to store it's member variables in one place, you may as well just make them all public.
The object would likely not require destructor (you only need a destructor if you need to cleanup resources, e.g. pointers, but if you're serializing a pointer, you're just asking for trouble). It's probably nice to have some syntax sugars constructors, but nothing really necessary.
If the data is just a Plain Old Data (POD) object for carrying data, then it's a candidate for being a struct (fully public class).
However, depending on your design, you might want to consider adding some behavior, e.g. an .action() method, that knows how to integrate the data it is carrying to your actual Model object; as opposed to having the actual Model integrating those changes itself. In effect, the DTO can be considered part of the Controller (input) instead of part of Model (data).
In any case, in any language, a getter/setter is a sign of poor encapsulation. It is not OOP to have a getter/setter for each instance fields. Objects should be Rich, not Anemic. If you really want an Anemic Object, then skip the getter/setter and go directly to POD full-public struct; there is almost no benefit of using getter/setter over fully public struct, except that it complicates code so it might give you a higher rating if your workplace uses lines of code as a productivity metric.