General question about OOP programming and haxe

Hi fellow haxers,

I am a bit rusty with OOP. This will probably a question with an easy answer, but in this question humans are a better friend to me than google :wink:

  • baseclass PrimitiveVisualObject representing a visual object on screen, with width, height, x, y and a background color.

  • class InteractiveVisualObject extends PrimitiveVisualobject, representing visual objects which the use can iteract with, it contains signals to mouse, touch and keyboard input.

  • class VisualObjectContainer extends InteractiveVisualObject, this class represents an object on screen which acts like a container for instances of itself, InteractiveVisualObject or PrimitiveVisualObject. VisualObjectContainer has functions like addChild, removeChild, etc. public function addChild(child:Dynamic):Void;

class PrimitiveControl extends VisualObjectContainer representing all the base functionality for a control framework. Classes like Button, TextInput etc extend this class.

PrimitiveVisualObject, the superclass of all of these classes has a private field:
private var _jquery:JQuery;

Is there a way for me not to have to use ā€œchild:Dynamicā€ within public function addChild(child:Dynamic):Void?
I tried this solution

typedef TVisualObject = {
     private var _jquery:JQuery;
}

public function addChild<TVisualObject >(child:TVisualObject ):Void{
   this._jquery.append(child._jquery); //this is not litteraly this code, but you get the idea
}

This didnā€™t seem to work. How to skin this cat?

Thanks a head,
Simon

It sounds like youā€™re trying to recreate something similar to flash Display hierarchy. Can I ask what is the purpose? Because basically, I canā€™t see the problem from your description.
Can you also please make some try.haxe out of it?

edit: Oh, I get it - just donā€™t make it private. typdefs (or interfaces) are meant for public api. Anyway, if _jquery is private, instance._jquery is illigle no matter what is the typedef.

I dont need someone to write my code ofcourse, that isnā€™t the topic of my question.

My question is how to get rid of the Dynamic type for child in

class VisualObjectContainer extends PrimitiveVisualObject {
     public function addChild(child:Dynamic):Void {
        // ... some code
    }
}

In my post I described I tried the typical Haxe ducktype solution (or should it be duckt tape solution ;-))

typedef TVisualObject = {
private var _jquery:JQuery;
}

public function addChild(child:TVisualObject ):Void{
this._jquery.append(child._jquery); //this is not litteraly this code, but you get the idea
}

But it somehow doesnt work. That is very much a haxe question and also a general OOP question as well

Sorry, Iā€™ve answered while youā€™ve replied.

Private members

Typedefs can contain private members in their definitions. This allows access to otherwise unavailable members.

class Foo {
    public function new() {}
    public function fullAccess() return true
    function restrictedAccess() return true
}

typedef Bar = {
    function fullAccess():Bool;
    private function restrictedAccess():Bool;
}

class Main {
    public static function main()
    {
        var foo = new Foo();
        foo.fullAccess();
        //Compiler Error: Cannot access to private field restrictedAccess
        foo.restrictedAccess();
        
        var bar:Bar = foo;
        bar.fullAccess();
        //No Error, this is allowed
        bar.restrictedAccess();
    }
}

This piece of documentation shows it is possible to get a friendly access via ductyping. Its older documentation, but I donā€™t see things changed so much on that department.

I figured if this works for interfacing instances, my solution should work as well. I just probably made some mistake I overlook. Or something did change and thatā€™s the reason why it doesnt work.
Maybe someone more experienced in this magical trickery can help me out, and this might also valuable to you as well :slight_smile:

Iā€™m here to learn.
Anyway, your question was about OOPā€¦ :wink:

Well an the haxe implementation of OOP. But you are correct, this is ofcourse a flthy hack on OOP purity :slight_smile:
It is ofcourse bad manners to have some sick ducttype exposing private parts of your classes/instances :slight_smile: haha

1 Like

Iā€™m not sure I understand exactly what you are asking, doesnā€™t:

public function addChild(child:PrimitiveVisualObject):Void {
    _jquery.append(child._jquery);
}

works?

Since _jquery is private in PrimitiveVisualObject and VisualObjectContainer extends it you should have access to it.
In haxe private is equal to protected in most other oop languages.

typedef TVisualObject = {
private var _jquery:JQuery;
}

The following you suggest is not valid
public function addChild(child:PrimitiveVisualObject):Void {
_jquery.append(child._jquery);
}

The issue is not that some class doesn have access to _jquery, the problem is that I want to give access to childs which are subclasses of PrimitiveVisualObject, and these classes can be subclasses like a container like class Control or just a simple subclass which is not a container just for example a simpe Shape (which is an svg under the bonnet).

Because when I use a far down the line subclass of PrimitiveVisualObject instance, letā€™s say an instance of class Button, (which subclasses Control which sublasses VisualObjectContainer, which subclasses InteractiveVisualObject which subclasses PrimitiveVisualObject) the compiler will say child got Button where it expects PrimitiveVisualObject. Haxe is too strict to allow in instance of Button for child. So the next best thing is to use ducktyping and make use of giving it acces to private field _jquery which should not be public as that field is implementation only and doesnt be part of the api

So that is why I want to know how I can make this

Typedefs can contain private members in their definitions. This allows access to otherwise unavailable members.

typedef TVisualObject = {
private var _jquery:JQuery;
}

public function addChild(child:TVisualObject ):Void {
_jquery.append(child._jquery);
}

work

Hmm Iā€™ve never seen any cases where you couldnā€™t pass a child (or grand grand grand child) to a function which expect the parent class.
Thatā€™s simply how inheritance works.

For instance Try Haxe!

What is the exact error message that you get? Are you sure that Button is indeed a sub(sub)class of PrimitiveVisualObject?

Alternatively if you really want to use the typedef method (which isnā€™t the exact same thing) it works too Try Haxe !

I think thereā€™s an error somewhere else in your code.

I think you are right, back to debugging