A basic question about communication between classes

Started by
2 comments, last by Katie 13 years, 6 months ago
As a very beginner of OOP, I created a bunch of classes and now hope them work together to finish a task. Now I have a basic question, how the classes communicate/interact with each other? based on my past sequential programming experience, I think there are possibly two solutions:

1) Write a main function, instantiate the classes there, and let the object calles the methods of other objects.
2) I can let objects send out a message instead of calling the methods of other objects inside of the same process. So all object have to check the message queue and parse the messages sent to them.

I would like to know if any other solutions available for communication/coordinate between classess in one process or in one application. What will be the most popular way? Is there any best way?

Thank you.
Advertisement
There are five main ways in which classes and objects can coordinate with others. They are not mutually exclusive. I'll list them in order of lowest level concepts to highest level concepts.

*Parameter Passing - The most basic method has been around for a long time. Back in C you would pass objects around as parameters and the functions would operate on the members. This is the most basic method of object interaction, I almost forgot to mention it. In C++ and other languages you might not act directly on public member variables, instead you would likely call member functions on the passed in objects, but this remains a staple.

*Inheritance - this isn't object interaction so much as it is class interaction. You can derive from other classes to extend your interfaces and either expose that inheritance publicly or utilize private inheritance to simply consume methods internally. An example might be a "DrawablePoint" class which is used in rendering which contains a "CoordinatePoint" and "Color" inheritance giving the DrawablePoint both all the methods of CoordinatePoint and Color (this is multiple inheritance and should be rarely used in preference of single inheritance).

*Object Composition - This is where each object of a class type has member variables which themselves are objects. Where inheritance widens the interface composition does not roll new behavior into an object automatically. Instead we rely on the parent class to coordinate and direct member objects in a meaningful way (as member variables should almost always be private or at least protected and not exposed publicly). An example would be having a tic tac toe board which contains a vector of "Slot" type objects which keep track of the state of each spot (x, o, or blank).

*Dependency Injection - This is a method of supplying references or pointers to other objects your class needs to interact with which may exist outside of the scope of the object that needs to use them. An example may be a "WorldObject" which requires a reference to the "Renderer" object in order to utilize its draw method. There are a lot of longer more complicated examples of this explained (the wikipedia article is particularly bad) and I'm trying to keep it simple.

*Callbacks/Events - Event based programming often relies on callbacks. Things such as the Observer pattern and the Command pattern implement this type of event based interaction a little differently... Callbacks are typically implemented with functors or function pointers (often templated so it doesn't matter which) and the standard library makes extensive use of this in the stl algorithms supplied which work off of iterators. This is a pretty broad topic though.

You can mix and match these concepts (some of them rely on each other) and end up with various uses which use a mixture of ideas. There may be others I'm missing, but this should cover the basics. Most other methods of class or object interaction are simply novel combination's or variations or implementations of these ideas.

You ask specifically:

Quote:I would like to know if any other solutions available for communication/coordinate between classess in one process or in one application. What will be the most popular way? Is there any best way?


There is no "best" way or "most popular" way. A hammer is no better than screwdriver when the two sit side by side on a workbench; but while a screwdriver is useful on screws you wouldn't use it to pound in a nail. Different problems call for different tools and solutions.

With that said, there are certain ways to misuse the tools I've listed. Maintaining a deep inheritance hierarchy with casually used multiple inheritance is one misuse. Events can often become confusing and hacky as they strongly decouple action from event and it can make following the program flow nearly impossible if it gets out of hand. Dependency injection can introduce ownership confusion. Parameter passing can introduce tight dependency all over the entire program such that it is hard to re-factor a method without affecting all instances of occurrence. Composition can get out of hand when complicated objects are made public and their interfaces change.

[Edited by - M2tM on October 14, 2010 7:43:43 PM]
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Quote:Original post by M2tM
There are five main ways in which classes and objects can coordinate with others. They are not mutually exclusive. I'll list them in order of lowest level concepts to highest level concepts.

*Parameter Passing - The most basic method has been around for a long time. Back in C you would pass objects around as parameters and the functions would operate on the members. This is the most basic method of object interaction, I almost forgot to mention it. In C++ and other languages you might not act directly on public member variables, instead you would likely call member functions on the passed in objects, but this remains a staple.

*Inheritance - this isn't object interaction so much as it is class interaction. You can derive from other classes to extend your interfaces and either expose that inheritance publicly or utilize private inheritance to simply consume methods internally. An example might be a "DrawablePoint" class which is used in rendering which contains a "CoordinatePoint" and "Color" inheritance giving the DrawablePoint both all the methods of CoordinatePoint and Color (this is multiple inheritance and should be rarely used in preference of single inheritance).

*Object Composition - This is where each object of a class type has member variables which themselves are objects. Where inheritance widens the interface composition does not roll new behavior into an object automatically. Instead we rely on the parent class to coordinate and direct member objects in a meaningful way (as member variables should almost always be private or at least protected and not exposed publicly). An example would be having a tic tac toe board which contains a vector of "Slot" type objects which keep track of the state of each spot (x, o, or blank).

*Dependency Injection - This is a method of supplying references or pointers to other objects your class needs to interact with which may exist outside of the scope of the object that needs to use them. An example may be a "WorldObject" which requires a reference to the "Renderer" object in order to utilize its draw method. There are a lot of longer more complicated examples of this explained (the wikipedia article is particularly bad) and I'm trying to keep it simple.

*Callbacks/Events - Event based programming often relies on callbacks. Things such as the Observer pattern and the Command pattern implement this type of event based interaction a little differently... Callbacks are typically implemented with functors or function pointers (often templated so it doesn't matter which) and the standard library makes extensive use of this in the stl algorithms supplied which work off of iterators. This is a pretty broad topic though.

You can mix and match these concepts (some of them rely on each other) and end up with various uses which use a mixture of ideas. There may be others I'm missing, but this should cover the basics. Most other methods of class or object interaction are simply novel combination's or variations or implementations of these ideas.

You ask specifically:

Quote:I would like to know if any other solutions available for communication/coordinate between classess in one process or in one application. What will be the most popular way? Is there any best way?


There is no "best" way or "most popular" way. A hammer is no better than screwdriver when the two sit side by side on a workbench; but while a screwdriver is useful on screws you wouldn't use it to pound in a nail. Different problems call for different tools and solutions.

With that said, there are certain ways to misuse the tools I've listed. Maintaining a deep inheritance hierarchy with casually used multiple inheritance is one misuse. Events can often become confusing and hacky as they strongly decouple action from event and it can make following the program flow nearly impossible if it gets out of hand. Dependency injection can introduce ownership confusion. Parameter passing can introduce tight dependency all over the entire program such that it is hard to re-factor a method without affecting all instances of occurrence. Composition can get out of hand when complicated objects are made public and their interfaces change.


Thank you very much for sharing and teaching! It is very informative.

I am also interested in the event or message handling mechanism of Linux kernel and wonder how efficient it is at this moment. Do you have anything to share?

Thank you!




The linux kernel systems are extremely efficient. Linux is written by geeks, and they like nothing better than to competitively out-optimise each other on esoteric kernel internals. Which is good for the rest of us because we get the end result of those competitions.

Generally the simplest way to talk between one process and another is to use sockets -- this is reasonably portable to other OSes and later on lets you have the two processes on different machines without much work.

Sockets can be pictured as two pipes of bytes (one going each way). As you push bytes in one end they're available for reading on the other. They appear as file descriptors so you can just read() and write() data with them.

There are other structures such as shared memory and semaphores and so on, but using them correctly can be a little tricky (there are things called race hazards to worry about which is more complicated than you probably need to be dealing with at the moment). I'd suggest ignoring them for the time being. If and when you need to know about them, you'll have enough exp to be able to play with them.

This topic is closed to new replies.

Advertisement