SuperClass Cast Problem

I have a superClass called “myShape”.
I have several subClasses like “mySquare” and “myCircle”.

In the superClasse (“myShape”) I have some global properties, like Xposition, Yposition, Width, Height, etc.
In de subClasses I can set shape specific values, like radius for the circle, etc.

I store the shape data in a dictionary.
Every time I draw the shapes a paint handler iterates through the dictionary, pulling the values as a “myShape”.
I do some cast checking like

if theShape isA myCircle then
  theCircle = theShape
  // drawing the circle
elseif theShape isA mySquare then
  // drawing the square
elseif theShape isA myImage then
  // drawing an image
end if


theCircle is local variable of type “myCircle”
theShape is a local variable of type “myShape” pulled from the dictionary

Problem is that I got a type mismatch error when I try this. (Expected class myCircle but got class myShape)
The above example is modified from my own project’s code. Otherwise there will be too much text here. I think the example here explains my problem good enough, I think :slight_smile:

You have to typecast the instances. Example:

if theShape isA myCircle then
  theCircle = myCircle(theShape)
  // drawing the circle
elseif theShape isA mySquare then
  // drawing the square
elseif theShape isA myImage then
  // drawing an image
end if

[quote=202045:@Edwin van den Akker]Every time I draw the shapes a paint handler iterates through the dictionary, pulling the values as a “myShape”.
I do some cast checking like[/quote]

Also: you might want to consider refactoring the code so that you don’t have to perform any type checking. It sounds like you’re just storing data in the classes. Create methods in myShape that you can override in child classes. Then you can have a simple array of type myShape and do something like:

for each theShape in theShapesArray
    // Each child class implements Draw and its own drawing code.
    // Just pass the graphics that the shape will draw to and you're done.
    theShape.Draw(g)
next

Wow, good thinking Daniel! You’re a lifesaver, thanks!

Daniel’s advice should be applied throughout your code. If you find yourself doing a large SELECT or IF/ELSEIF statement, there is probably a better, more OOP-oriented way to do it.

In cases where I will never directly instantiate a superclass, I like to raise an event in the subclasses. So the Draw method would be in the superclass and would contain one line of code:

Sub Draw (g As Graphics)
  RaiseEvent Draw( g )
End Sub

Each subclass would then implement the Draw event.

BTW, consider using “Paint” instead of “Draw” for consistency with the native objects.

What do you mean? Like, create a method “Paint” instead of “Draw”?
I don’t really see why. I use “draw” like the draw method on the Graphics object. But instead of saying “DrawOval”, I let the subClasses take care of what I draw, based on the type of object that is passed from the objectArray (or dictionary, in my case)

I think what Kem is getting at is that if you take his suggestion to use events rather then methods you should use the same name/parameters as other classes in Xojo, which would be Paint(g as Graphics).

If you stick with methods I think Draw is preferable naming.

When might you implement/inherit behavior via events instead of methods?

  • When individual instances of a class need to be able to define completely open and arbitrary behavior. (Think of all the different examples of code that get put in, say, PushButton.Action.)

  • When other objects need to be able to attach behavior to specific instances via AddHandler.

Always keep in mind that events travel down the class hierarchy rather then up. ParentClass.MyEvent gets the event, and ChildClass.MyEvent only gets it if ParentClass raises the event. With methods the opposite is true: ChildClass.MyMethod gets the method call, and ParentClass.MyMethod only gets called if the child invokes Super.MyMethod.

The bulk of the functionality in your classes will probably be implemented and inherited via methods. But sometimes events are quite useful.

I understand what you mean David.
I do prefer events over methods in this manner. The thing is, although I actually use events very often, I have this project that makes use of subclasses, and even subclasses of subclasses:

SomeObjectToDraw,ShapeObject.CircleObject
or
SomeObjectToDraw.ImageObject
or
SomeObjectToDraw.TextObject

The objects are stored in an array or dictionary as the master SomeObjectToDraw class.
I only need to find a way to figure out how I know if an object is overlapping.

Most objects have the exact type of data. Like position and dimensions. The child object use these properties to store that kind of data. An image is not needed in a circle, therefore only implemented in that child object.

A draw method is used in every Class or Subclass. A subclass draw method does the drawing in the passed g as iosGraphics parameter end with a super.draw, to finish drawing labels if needed. The masterClass resets the canvas in it’s draw method. So, paint is doable, as I think of it now. But it was not just my approach.

There are more roads that lead us to Rome, as an expression says :wink:

Call me stupid… but I even tried creating something like a mask-like image in-memory, a black and white representation of an object. After that I only had to compare positions on the main canvas’ graphics object and the one on my “mask”.

But this is not a preferable approach, of course. It eats up CPU time, And it is not the memory’s best friend.

So, now, when I have an object that needs to move though gestures, PointerDown results in the clicked object to move to the top in an Array. If two objects overlap the top one is selected, the underlying objects are going to be ignored.

Another benefit for an overridden method over an event is that you can make sure it’s implemented. If you define an event, there is no way to tell if the subclass executed it without having the subclass return something like a boolean. But you can alway define the super’s method as something like:

Sub YouShouldOverride()
  dim err as new RuntimeException
  err.Message = "The subclass must override this method"
  raise err
End Sub

That will give you a not-so-subtle reminder at runtime. :slight_smile:

(But I still like events. :slight_smile: )

Personally, I really only use events where behavior has to be specified per instance (as opposed to per class), even though an event can be used to specify class wide behavior. Events are basically a response mechanism, i.e. “this happened at an arbitrary time therefore I need to do x.” Methods, inheritance, and interfaces…classic OOP tools…are designed for modeling behavior and communication between separate objects on a large scale.

Part of the reason for my preference is the glue code required for events. Events have to be defined and raised at each step down a hierarchy if you want every child class to get a shot at the event. And events cannot be raised from outside the class, which means glue methods if you want outside classes to be able to invoke events.

But they have the power of instance level behavior. At times that is very useful.

Methods have the same ability, just in reverse. While an event will start at the top and must be raised to the subclasses, a method will start at the last subclass to implement that method with the same signature. That method can then send it up the chain using super.MyMethod.

both have their own set of issues they solve / cause

But it’s implicitly available with methods. Any child class can extend (via super) or completely override a method just by matching the signature. With an event the parent class has to redefine and raise the event for a child class to have the option to extend behavior. Not override, merely extend, because the parent code will execute absent some other signaling mechanism (i.e. a returned value from the raised event).

Whether these differences are pros or cons depends entirely on the problem you’re trying to solve. Sometimes you want the parent class to have a guaranteed first shot at a response (for example). But methods do have less ‘glue’ for behavior that is defined, extended, and overridden across a class hierarchy.

[quote=202290:@Edwin van den Akker]The objects are stored in an array or dictionary as the master SomeObjectToDraw class.
I only need to find a way to figure out how I know if an object is overlapping.[/quote]

Missed this earlier…

From an OOP standpoint if you’re trying to determine which shape should respond to a click (or tap or whatever pixel point) you could do something like this:

for each theShape in theShapesArray
    if theShape.Contains(x,y) = true then
        // Whatever response you want.
    end if
next

Contains would be an empty method that returns false for your parent class. Each child class would implement Contains with hit testing appropriate to the shape.

You’ll probably want to loop through the shapes in front-to-back order so that the top most shape containing a point is the first or only shape to respond.

Now as to the details of actual hit testing inside of the Contains method…

This stack overflow post gives a good description of how to approach this for polygons. This post discusses the problem in relation to an ellipse.