Help with pseudo multi inheritance

 

I've built a pseudo inheritance since mql doesn't allow this, here's what i did.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CLocalShop;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CVendor : public CObject
  {
private:

   string            m_id;

public:
                     CVendor(string id) {m_id=id;}

   void setid(string id) {m_id=id;}
   string getid() {return m_id;}

   void askForResupply() {PrintFormat("Please resupply me, vendor %s.",m_id);}

  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCustomer : public CObject
  {
private:

   string            m_name;

public:
                     CCustomer(string name) {m_name=name;}

   void setname(string name) {m_name=name;}
   string getname() {return m_name;}

   void sendOrder() {PrintFormat("Dear %s we are sending your goods.",m_name);}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CVendorAUX : public CVendor
  {

public:

   CLocalShop       *shop;

   //CVendorAUX();
                     CVendorAUX(string id,CLocalShop *p) : CVendor(id) {shop=p;}

  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCustomerAUX : public CCustomer
  {

public:

   CLocalShop       *shop;

   //CCustomerAUX();
                     CCustomerAUX(string name,CLocalShop *p) : CCustomer(name) {shop=p;}

  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CLocalShop
  {

private:

   string            m_address;

public:

   CVendorAUX       *vendor;
   CCustomerAUX     *customer;

   void setaddress(string address) {m_address=address;}
   string getaddress() {return m_address;}

                     CLocalShop(string vendorId,string customerName,string address);
                    ~CLocalShop();

  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CLocalShop::CLocalShop(string vendorId,string customerName,string address)
  {
   vendor=new CVendorAUX(vendorId,GetPointer(this));
   customer=new CCustomerAUX(customerName,GetPointer(this));
   m_address=address;

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CLocalShop::~CLocalShop()
  {
   delete vendor;
   delete customer;
  }
//+------------------------------------------------------------------+
#include "myExample.mqh"
#include <Arrays/ArrayObj.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   CVendor *ibm= new CVendor("32FK-IBM");
   CVendor *hp = new CVendor("1138-HP");
   CCustomer *mrSimpson=new CCustomer("mr. Simpson");
   CCustomer *mrGates=new CCustomer("mr. Gates");
   CLocalShop *joys=new CLocalShop("1979-JS","Joys Computer Shop","123, Fake St.");
   CLocalShop *zama=new CLocalShop("451-SS","Mercatone UNo","Cazzo, 2");

   CArrayObj list;

   list.Add(ibm);
   list.Add(hp);
   list.Add(joys.vendor);
   list.Add(zama.vendor);

   for(int i=0; i<list.Total(); i++)
     {
      CVendor *ven=list.At(i);
      ven.askForResupply();
     }

   list.Clear();
   list.Add(mrSimpson);
   list.Add(mrGates);
   list.Add(joys.customer);
   list.Add(zama.customer);

   for(int i=0; i<list.Total(); i++)
     {
      CCustomer *cust=list.At(i);
      cust.sendOrder();
     }

   delete ibm;
   delete hp;
   delete mrSimpson;
   delete mrGates;
   delete joys;
   delete zama;
  }
//+------------------------------------------------------------------+

I want to improve this part:

   list.Add(ibm);
   list.Add(hp);
   list.Add(joys.vendor);
   list.Add(zama.vendor);

is there a way to add CLocalShop object and automatically pass CVendorAux if the collection is of CVendor object? same for CCustomer?

any other things to improve or correct? i'm asking the veteran here, i'm trying to learn best practice and pattern for coding, i've no experince exept mql.


thanks


edit: accidentally posted thread without finishing it and formatting

 

Use SRC button to post code.


 
d.bignotti:

I've built a pseudo inheritance since mql doesn't allow this, here's what i did.

I want to improve this part:

is there a way to add CLocalShop object and automatically pass CVendorAux if the collection is of CVendor object? same for CCustomer?

any other things to improve or correct? i'm asking the veteran here, i'm trying to learn best practice and pattern for coding, i've no experince exept mql.


thanks


edit: accidentally posted thread without finishing it and formatting


This is not really a good example of inheritance since your objects do not maintain the "IS A" relationship. A local shop is a vendor? A local shop is a customer?


A better example is if you have a class that needs to implement more than one base class. 

class Base1
{
   virtual int Type()=0;
};

class Base2
{
   virtual string ToString()=0;
};

Let's say you had an existing class that derived Base1

class MyClass : public Base1 {};

Now Let's say you needed MyClass to also inherit Base 2. Without multiple inheritance you would need to fork the class and declare it like this.

class Base1
{
   virtual int Type()=0;
};

class Base2 : public Base1
{
   virtual string ToString()=0;
};



class MyClass : public Base2 {};
 
d.bignotti:

...

any other things to improve or correct? i'm asking the veteran here, i'm trying to learn best practice and pattern for coding, i've no experince exept mql.

...

In my opinion, a best practice is to not "force" a pattern usage when the language doesn't provide all the needed features.
 
Alain Verleyen:
In my opinion, a best practice is to not "force" a pattern usage when the language doesn't provide all the needed features.

Multiple inheritance is not a requirement for the pattern. 

 

This topic is linked to this one Observer pattern, right ?

So, if multiple inheritance is not required, it is needed if someone is trying to code "pseudo" multiple inheritance (I am talking about multiple inheritance of interface or any other form), coding it without a kind of inheritance is possible but is a limitation, and need to think about it carefully for the pattern to remain useful. Of course you can always find tricks to have it "working", I have even read about copy and paste as an OOP "technique" (isn't OOP about code re-usability ?). Or you can implement the subject/observer "interfaces" in the super class <CObject>, but while doing that you need to be aware of the possible consequences.

Why and when is the Observer pattern needed and usable ? From the "Design Patterns: Elements of Reusable Object-Oriented Software" (from the well known Gang of Four or GoF), we can read that :

When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently

When a change to one object requires changing others, and you don't know how many objects need to be changed. 

When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.

Are your objects reusable and independent ? are they not-tightly coupled ? If the way you coded them and use the Observer pattern lead to answer in a negative way to these questions, then the purpose to use this pattern is defeated.

OOP is a good programming paradigm, design patterns are great best practices...if used correctly and lead to better code.

So, are your objects reusable, independent, not-tightly coupled ? I have some difficulties to think all the proposed implementation will answer yes to all these questions. That doesn't mean it's not worth to implement the Observer pattern in the way you want, to have a functional code, of course, but don't expect to be able to reuse it later in an other project if it's not well conceived.


At the bottom of this post, you will see an implementation using templates, and which doesn't use multiple inheritance. Why not try it in mql5 ?


Finally some news ...

An easy to use Observer Pattern Implementation (no inheritance required) - CodeProject
An easy to use Observer Pattern Implementation (no inheritance required) - CodeProject
  • Corneliu Tusnea
  • www.codeproject.com
Observer Pattern implemented in a nice template model, easy to use as it does not require the classical inheritance and can easly decouple Subject and Observer. Introduction The Observer Pattern (Gamma) is part of lots of implementations and is one of the most used patterns. However, implementing a flexible Observer pattern is not an easy task...
 
Alain Verleyen:

This topic is linked to this one Observer pattern, right ?

So, if multiple inheritance is not required, it is needed if someone is trying to code "pseudo" multiple inheritance (I am talking about multiple inheritance of interface or any other form), coding it without a kind of inheritance is possible but is a limitation, and need to think about it carefully for the pattern to remain useful. Of course you can always find tricks to have it "working", I have even read about copy and paste as an OOP "technique" (isn't OOP about code re-usability ?). Or you can implement the subject/observer "interfaces" in the super class <CObject>, but while doing that you need to be aware of the possible consequences.

Why and when is the Observer pattern needed and usable ? From the "Design Patterns: Elements of Reusable Object-Oriented Software" (from the well known Gang of Four or GoF), we can read that :

Are your objects reusable and independent ? are they not-tightly coupled ? If the way you coded them and use the Observer pattern lead to answer in a negative way to these questions, then the purpose to use this pattern is defeated.

OOP is a good programming paradigm, design patterns are great best practices...if used correctly and lead to better code.

So, are your objects reusable, independent, not-tightly coupled ? I have some difficulties to think all the proposed implementation will answer yes to all these questions. That doesn't mean it's not worth to implement the Observer pattern in the way you want, to have a functional code, of course, but don't expect to be able to reuse it later in an other project if it's not well conceived.


At the bottom of this post, you will see an implementation using templates, and which doesn't use multiple inheritance. Why not try it in mql5 ?


Finally some news ...

Or in plain English, soon will be multiple inheritance in mql5 ;-)

Are you trying to say that cloning some classes into your project folder and making minor tweaks to those classes in order to suit the needs of your project -- is not good OOP practice???  I hate to be the one to break it to you, but cloning and forking code is an extremely common practice in the real world. 

 
Alain Verleyen:

This topic is linked to this one Observer pattern, right ?

So, if multiple inheritance is not required, it is needed if someone is trying to code "pseudo" multiple inheritance (I am talking about multiple inheritance of interface or any other form), coding it without a kind of inheritance is possible but is a limitation, and need to think about it carefully for the pattern to remain useful. Of course you can always find tricks to have it "working", I have even read about copy and paste as an OOP "technique" (isn't OOP about code re-usability ?). Or you can implement the subject/observer "interfaces" in the super class <CObject>, but while doing that you need to be aware of the possible consequences.

Why and when is the Observer pattern needed and usable ? From the "Design Patterns: Elements of Reusable Object-Oriented Software" (from the well known Gang of Four or GoF), we can read that :

Are your objects reusable and independent ? are they not-tightly coupled ? If the way you coded them and use the Observer pattern lead to answer in a negative way to these questions, then the purpose to use this pattern is defeated.

OOP is a good programming paradigm, design patterns are great best practices...if used correctly and lead to better code.

So, are your objects reusable, independent, not-tightly coupled ? I have some difficulties to think all the proposed implementation will answer yes to all these questions. That doesn't mean it's not worth to implement the Observer pattern in the way you want, to have a functional code, of course, but don't expect to be able to reuse it later in an other project if it's not well conceived.


At the bottom of this post, you will see an implementation using templates, and which doesn't use multiple inheritance. Why not try it in mql5 ?


Finally some news ...

Or in plain English, soon will be multiple inheritance in mql5 ;-)

Good news form MetaQuotes, guess i'll wait for multi inheritance support. 

 
nicholishen:

Multiple inheritance is not a requirement for the pattern. 


Of course it is a requirement, and you can also bypass it with consequences as Alain said. 
For instance, your code does not support an observer that observes several subjects. 
And you did not inherit Subject into a concrete subject, which makes the example useless.

I don't say you can not overcome those, you can. But they are flaws right now. 
BTW, I use observer for few years now.

* Actually, you need to inherit subject + inherit observer - which you didn't do.

 
Amir Yacoby:

Of course it is a requirement, and you can also bypass it with consequences as Alain said. 
For instance, your code does not support an observer that observes several subjects. 
And you did not inherit Subject into a concrete subject, which makes the example useless.

I don't say you can not overcome those, you can. But they are flaws right now. 
BTW, I use observer for few years now.

* Actually, you need to inherit subject + inherit observer - which you didn't do.

This is a total straw man argument you setup here. You can rewrite the class to implement the same interfaces as it would with multiple inheritance by cloning the class and forking it's code. Just because I did a simple conversion from the Java example and didn't waste the time in making a fully working mql snippet doesn't change the fact that if I want a mql class to implement multiple interfaces then I can easily change its declarations to do so. 
 
nicholishen:
This is a total straw man argument you setup here. You can rewrite the class to implement the same interfaces as it would with multiple inheritance by cloning the class and forking it's code. Just because I did a simple conversion from the Java example and didn't waste the time in making a fully working mql snippet doesn't change the fact that if I want a mql class to implement multiple interfaces then I can easily change its declarations to do so. 
Sorry, I don't mean to bug you.
Yes you can do that.
For instance:
class CSubject {}
class CObserver : public CSubject {}
class CObserverWrapper : public CObserver {}

But with several drawbacks:
1. It is not a neat structure
2. All your objects become subject and observer regardless if they use it or not
3. You cant apply all the patterns in this way.

As we agree on the observer I will stop commenting about it in this context.
Reason: