Class Design question

  1. 3 months ago

    Alexander v

    Jul 4 Europe (Houten, The Netherland...

    I'm developing a class (ClassA) which behavior will be influenced by another class (ClassB).
    Somewhere in a method of ClassA I have to write:

    If ClassB.Property1 = False then
      do this
    else
      do that
    end if

    But ClassA doesn't now how ClassB will be implemented. Moreover, I was always taught that classes should be agnostic of each other. How to solve this?

    change

    Return RaiseEvent Paint(g,areas)

    to

    RaiseEvent Paint(g,areas)

    the PAINT event inherited from Xojo classes like canvas etc has NO return value so you cannot return anything

  2. Jean-Yves P

    Jul 4 Pre-Release Testers, Xojo Pro Europe (France, Besançon)

    make a private property in classA named "myclassB" and type ClassB
    make a constructor to assign the classB to the classA
    refer to the classB with the property myClassB from classA

  3. James D

    Jul 4 Pre-Release Testers, Xojo Pro Europe (Switzerland)
    Edited 3 months ago

    @Alexander vnbsp;der Linden Moreover, I was always taught that classes should be agnostic of each other. How to solve this?

    If we tried to do that, we never get anything done...... They should have no knowledge of or reliance on how the other class has been implemented.

    So the first thing to sort out: Are you talking about a property of the class or a property of an instance of a class?

    If you are referring to a property of the class, then the class must exist, otherwise wise it will not fly.

    If you are referring to a property of an instance of class B, then the instance of class A must in some why receive a reference to the instance of class B, either in it's constructor or as a parameter to a method call on the instance.

    In order to handle the fact that the class has not been defined, you need to introduce an interface into the equation, so class A would then interact with the interface rather than class b. Later when you come to create class b, you need to have it implement the interface so it can interact with class A.

  4. Massimo V

    Jul 4 Pre-Release Testers, Xojo Pro Europe (Germany, Würzburg)

    This is a perfect situation for the Observer pattern. You can find examples in the Xojo Examples folder.

  5. @Alexander vnbsp;der Linden — Classes cannot be agnostic of each others. If your class A uses class B, then it has to know how to use it and A becomes dependent on B. That is perfectly normal.

  6. Massimo V

    Jul 4 Pre-Release Testers, Xojo Pro Europe (Germany, Würzburg)

    @Stéphane ;Mons @Alexander vnbsp;der Linden — Classes cannot be agnostic of each others. If your class A uses class B, then it has to know how to use it and A becomes dependent on B. That is perfectly normal.

    This is not necessary, though possible.
    If you use interfaces as the Observer pattern does, the class only know the interface.

  7. @Massimo V — True, but one way or another, there must be some exchange about how to use a class, be it

    1. a class declaration
    2. an interface
    3. Introspection (i.e. a dynamic class declaration)
  8. Norman P

    Jul 4 Pre-Release Testers, Xojo Pro great-white-software.com/blog
    Edited 3 months ago

    @Alexander vnbsp;der Linden I'm developing a class (ClassA) which behavior will be influenced by another class (ClassB).
    Somewhere in a method of ClassA I have to write:

    If ClassB.Property1 = False then
      do this
    else
      do that
    end if

    But ClassA doesn't now how ClassB will be implemented. Moreover, I was always taught that classes should be agnostic of each other. How to solve this?

    Use an interface
    Then have classB implment that interface
    An interface is quite literally a contract about how a class will behave but NOT about its implementation of that behaviour
    ClassA then has a property that refers to an instance that IS the interface type and you have some API for setting that

    Then your code is more like

    If ClassB.ShouldDoThat = False then
      do this
    else
      do that
    end if

    and you're not reaching into the guts of the implementation (ie reading a property)

  9. Alexander v

    Jul 4 Europe (Houten, The Netherland...

    Thanks all for the response. Food for thought.

    @James D So the first thing to sort out: Are you talking about a property of the class or a property of an instance of a class?

    It's a property of an instance of that class. That's why it doesn't know what it's name will be. I haven't yet worked with interfaces or constructors yet. I could reach my goals perfectly without it.

  10. Norman P

    Jul 4 Pre-Release Testers, Xojo Pro great-white-software.com/blog

    Interfaces are really simple
    Basically when you say a class implements an interface what you are promising is that the class will implement all of the methods of the interface - it can implement others as well but they arent part of the agreed to "contract"
    It makes it so that you can swap the actual instance out for a different one as long as they both implement the interface

    For instance, suppose you have a bunch of classes that are unrelated so a class hierarchy makes no sense. Maybe there is a class for a Car, and a Horse. A car is not a horse and the horse is not a car so its unlikely they have any relationship in their super classes.

    But, both can MOVE. How they move is different.

    So they might both implement a "Movable" interface which has one method - Move(inDirection as integer)
    We can debate about direction as an integer - but accept that this means "move in a given direction"

    So we have

    Interface Movable
        Sub Move(inDirection as integer)
    End Interface

    And then we make Car implement Movable

    Class Car
        Implements Movable
    
        Sub Move(inDirection as integer)
             // in here we write the code for how to move a car
        End Sub
    
        .... // other methods & properties of a Car
    End Class

    And Horse implement Movable

    Class Horse
        Implements Movable
    
        Sub Move(inDirection as integer)
             // in here we write the code for how to move a horse
        End Sub
    
        .... // other methods & properties of a Horse
    End Class

    Now anything that knows how to tell a Movable to move can use either a car or a horse and really doesnt care which it is
    It knows its "Movable"

    dim m as Movable
    
    m = new Car
    m.move(129)
    
    m = new Horse
    m.move(129)

    And since an interface IS a new type you can also do things like ISA tests

    dim v as Variant
    v = new Car
    
    if v isa Movable then
      Movable(v).move(129)
    end if
  11. Alexander v

    Jul 4 Europe (Houten, The Netherland...

    Hi Norman,

    thanks. I thinks I grasp the basics. But this is about methods. What I want to share between classes is the outcome of a calculation which is stored in a property in class Horse but is needed in class Car. But class Car doesn't know if class Horse is implemented as MyHorse of MrEd and I tried already but either way it won't compile.

  12. Norman P

    Jul 4 Pre-Release Testers, Xojo Pro great-white-software.com/blog

    make the method in the interface a FUNCTION that returns a value
    you still need some reference to the class - whether that is saved as a property in the class relying on the other one or not

    suppose Movable includes a "DistanceMoved() as Integer" function
    then any things that knows about "movable" can also find out how far the thing moved when told to move

    dim m as Movable
    
    m = new Car
    m.move(129)
    if m.DistanceMoved() < 100 then
        /// .... etc
    end if
    
    m = new Horse
    m.move(129)
    if m.DistanceMoved() < 100 then
       // etc .....
    end if

    Same for your case

  13. Alexander v

    Jul 4 Europe (Houten, The Netherland...

    @Norman P make the method in the interface a FUNCTION that returns a value
    you still need some reference to the class - whether that is saved as a property in the class relying on the other one or not

    suppose Movable includes a "DistanceMoved() as Integer" function
    then any things that knows about "movable" can also find out how far the thing moved when told to move

    dim m as Movable
    
    m = new Car
    m.move(129)
    if m.DistanceMoved() < 100 then
        /// .... etc
    end if
    
    m = new Horse
    m.move(129)
    if m.DistanceMoved() < 100 then
       // etc .....
    end if

    Same for your case

    Works! Thanks

    Another question: I have a Canvas subclass in which I already use the Paint event to draw a specific pattern. But I want the Paint event to be available for the user as well. So I added an event definition 'Paint' and in the Paint event I do my drawing and I tried to use

    Return RaiseEvent Paint(g as Graphics, areas() as REALbasic.rect)


    but that won't compile. How to use the Paint event and make it available again?

  14. Norman P

    Jul 4 Pre-Release Testers, Xojo Pro great-white-software.com/blog
    Edited 3 months ago

    Return RaiseEvent Paint(g , areas )

    the data type declaration as integer and as REALbasic.Rect are only needed when you first define the method event etc

  15. Alexander v

    Jul 5 Europe (Houten, The Netherland...

    Tried that:

    Event Paint(g as Graphics, Areas() as REALbasic.Rect) As Graphics
    Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
      
      G.ForeColor = Me.GridColor
      
      For I As Integer = 1 To Me.Width Step (Me.BlockSize + Me.GridSize)
        For J As Integer = 1 To Me.Height Step (Me.BlockSize + Me.GridSize)
          G.FillRect(I,J,Me.Blocksize,Me.Blocksize)
        Next
      Next
      
      Return RaiseEvent Paint(g,areas)
      
    End Sub

    Compiler error: PlayCanvas.Paint, line 10
    You cannot return a value because this method has not defined a return type
    Return RaiseEvent Paint(g,areas)

  16. Norman P

    Jul 5 Pre-Release Testers, Xojo Pro great-white-software.com/blog

    the error tells you exactly whats wrong
    the paint event you ADDED can return a value but the PAINT event you implemented in the class cannot RETURN a value

  17. Alexander v

    Jul 5 Europe (Houten, The Netherland...

    I'm kinda lost here. How to solve this?

  18. Norman P

    Jul 5 Pre-Release Testers, Xojo Pro Answer great-white-software.com/blog

    change

    Return RaiseEvent Paint(g,areas)

    to

    RaiseEvent Paint(g,areas)

    the PAINT event inherited from Xojo classes like canvas etc has NO return value so you cannot return anything

  19. Alexander v

    Jul 5 Europe (Houten, The Netherland...

    Ahh! Of course. Many thanks

or Sign Up to reply!