LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Subclasses inheritance

Solved!
Go to solution
Solution
Accepted by topic author s.h._tech

@s.h._tech wrote:

@cbutcher wrote:

Further, following my descriptions above, are you happy that your Child is-a Parent?


A parent for which class? In this example?  A child can have a child (with all the methods and variables of the parent -> grandchild), but I dont think I did it here


In this case, I meant the relationship, not the level of inheritance. Let me give a commonly used example:

  • Suppose you have a Shape class. This is your parent
  • You have a Circle and a Rectangle class, these are your children
  • Now you want a Square. You figure that a square is a rectangle - it just has equal length sides. So you implement Square as a child of Rectangle.
    • "Get Area" continues to work - return height*width
    • "Set Width" and "Set Height" are a bit odd - in the rectangle case, one of these doesn't affect the other, but for a square, you just update a single length with either.
    • Imagine the following:
      • I have a "Rectangle" wire type. The area of the object is 12, the height is 3 and the width is 4.
      • I use "Set Height" and give a value of 8. I get the area and find that the result is 64, even though I expected 32. What happened?!
      • Of course it turns out the object was a Square, which doesn't necessarily have an is-a relationship with a Rectangle. It's a special case.
      • It would be even worse if I modeled them the other way, with Rectangle a child of Square. In that case, I have almost no value from the relationship (because Rectangle is very rarely a square, and essentially differs in the key point)

What I mean in your case is are you sure that, if you have a wire type of Datahandler, you would always do the same things if it turned out the object was really an "Input.lvclass", or some other child?

If you need to know the child type at edit time, you lose most of the benefits of dynamic dispatch - because you're specifically coding based on a subtype.

Note this isn't the same as being able to know the child type at edit time - for example, as a block diagram constant because it governs your current setup. In that case, you can quickly switch between different e.g. hardware/methods/whatever you're using a class for by changing just one constant (and perhaps some initialization code in a single VI that creates the object, depending on the requirements and your architecture).

 

Edit: Here are some links with probably better explanations than mine: Circle-ellipse_problem (Wikipedia)Why would Square inheriting from Rectangle be problematic if we override the SetWidth and SetHeight ...


GCentral
Message 21 of 28
(1,288 Views)

@s.h._tech wrote:

The 'datahandler' is the super class. I do some calculation, file manipulation, setting values that all 'Children' need. After the 'datahandler' has finished its initialization I create the 'Children' are created. These children now need the values of the 'Datahandler' (which where created earlier).

 


@cbutcher wrote:

From the code you just attached and the block diagram you show in your reply, you could now use the idea I suggested some time ago with a separate typedef'd cluster, not used in the private data, but only as an output. This would in your example be {Numerisch, Boolesch}.

I will use this method. I am used to have direct access to all variables of the super class without the need to implement specific setter methods from the parent (they share the same set of variables declared in the super class). It would be nice to unbundle the Elements of the 'Parent' directly in the 'Child'.

 


@cbutcher wrote:

Further, following my descriptions above, are you happy that your Child is-a Parent?


A parent for which class? In this example?  A child can have a child (with all the methods and variables of the parent -> grandchild), but I dont think I did it here


No, the question is if the Child is-a datahandler?

If they're not, they shouldn't be children.

If they are, the children should be created as such as data set within them (possibly through parent method).

If the datahandler is a superclass, then it should have an array of [whatever your current 'child' is]. If they are, they should be created.

 

Why not draw an UML diagram explaining how it's supposed to work?

 

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 22 of 28
(1,275 Views)

In fact, "is a" isn't enough, as cbutcher exemplifies. You also need to ask yourself if the child behaves as the parent. Like: a square is a rectangle, but it does not behave as one. But one could say that a square is a shape and behaves as a shape (although in some systems even that might be questionable).

The rectangle-square problem is excellently described this interview with Uncle Bob.

 

Certified LabVIEW Architect
0 Kudos
Message 23 of 28
(1,269 Views)

@Intaris wrote:

@s.h._tech wrote:

It would be nice to unbundle the Elements of the 'Parent' directly in the 'Child'.

And this is precisely what you can't do.

You create accessors for the parent, and use these inthe child isntead of direct cluster access.

This is how it works.

If you want to re-create all of the data in a child, then it's going to be really inefficient.


That means I need to create setter/getter methods in the parent to access the data of the parent in the child. So I need a extra method to extract data which should be inherited? 

The whole reason of an abstract class structure is to have the same access to methods and variables of the superclass. The methods are usually tied to the variables defined in the superclass and the child wants direct access and not an extra getter method to acess the variable which is already defined in the superclass-subclass structure. This seems unnecessary complicated

0 Kudos
Message 24 of 28
(1,260 Views)

Taking directly from the first google result for "get parent variable c++",

class Base
{
public:
    std::string mWords;
    Base() { mWords = "blahblahblah" }
};

class Foundation
{
public:
    Write( std::string text )
    {
        std::cout << text;
    }
};

class Child : public Base, public Foundation
{
    DoSomething()
    {
        this->Write( this->mWords );
        // or
        Foundation::Write( Base::mWords );
    }
};

shows the syntax in C++ for getting the parent values. Here "::" is essentially a 'getter' of sorts. (I know, not really... but it is a piece of syntax that declares where you should find the data, at least...)

 

Each language has its own syntax. For LabVIEW, all class data is private, and so the example above (where std::string mWords is declared public) is impossible (at least directly).

 

But making it accessible to a child isn't difficult, and with quick drop, it's faster for me to get parent data using an accessor than child data using an unbundle in the child's VIs 😉


GCentral
Message 25 of 28
(1,254 Views)

You may be right. Depends on the case.

 

Since I got my structure working I mark the problem as solved. 

 

Sadly I can only mark one solution as answer. The real answer is the combination of most of them

0 Kudos
Message 26 of 28
(1,245 Views)

@s.h._tech wrote:

Since I got my structure working I mark the problem as solved. 


If you still have questions/further thoughts (on the same topic) then feel free to keep going. If you have a different question or topic (even if related) probably best to start a new thread.

 


@s.h._tech wrote:

Sadly I can only mark one solution as answer. The real answer is the combination of most of them


Actually, you can mark as many solutions as you like, but generally it's best to keep the number fairly low (since the "answer(s)" are highlighted, and if everything is highlighted, it doesn't really help). For other contributions that are helpful, we often use kudos (the star icon).


GCentral
0 Kudos
Message 27 of 28
(1,237 Views)

@s.h._tech wrote:

So I need a extra method to extract data which should be inherited? 

Yes. It IS Inherited, but encapsulation means that a child, just like an external piece of code, needs to be granted access to the internal values via accessors. Only difference is that protected accessors are available to children, but not external code.

 

You are mixing up the inability to directly unbundle with data NOT being inherited.....

 

0 Kudos
Message 28 of 28
(1,230 Views)