Two questions about OOP

BlitzMax Forums/BlitzMax Beginners Area/Two questions about OOP

jankupila(Posted 2010) [#1]
Type GraphicalObject

	Field x:Float
	Field y:Float
	
	Method Draw(off_x:Float = 0, off_y:Float = 0) Abstract

EndType

Type Circle Extends GraphicalObject

	Field r:Float
	
	Method Draw(off_x:Float = 0, off_y:Float = 0)
		DrawOval (x+off_x, y+off_y, r, r)
	EndMethod

EndType

Type Box Extends GraphicalObject

	Field w:Float
	Field h:Float
	
	Method Draw(off_x:Float = 0, off_y:Float = 0)
		DrawRect(x+off_x, y+off_y, w, h)
	EndMethod

EndType

Type Text Extends GraphicalObject

	Field text:String
	
	Method Draw(off_x:Float = 0, off_y:Float = 0)
		DrawText( text, x+off_x, y+off_y)
	EndMethod
	
EndType

Graphics 640,480

HideMouse 

t1:Circle = New Circle
t1.x = 20
t1.y = 100
t1.r = 20

t2:Circle = New Circle
t2.x = 120
t2.y = 100
t2.r = 20

t3:Box = New Box
t3.x = 0
t3.y = 60
t3.w = 60
t3.h = 20

t4:Box = New Box
t4.x = 100
t4.y = 60
t4.w = 60
t4.h = 20

t5:Text = New Text
t5.x = 00
t5.y = 20
t5.text = "This is a Test"


While Not KeyHit(KEY_ESCAPE)
	Cls
	
    t1.Draw()
    t2.Draw()
    t3.Draw()
    t4.Draw()
    t5.Draw()
	
	Flip
Wend


This piece of code is taken from Kurator, OOP: Polymorphism for beginners. If you can, help me. In type graphical object, why only method 'draw' is marked abstract? After all whole type is inherited (Is that correct expression?). For example fields x and y are inherited to type circle. My logic say that type graphical object should be like this: 'Type GraphicalObject abstract.' I tried it and it works. And a other question: Why there is method 'Draw(off_x:Float = 0, off_y:Float = 0) Abstract' in type 'GraphicalObject'? Every extended type has 'draw' method of their own. Sorry about my bad English . It isn't my mother language.

Last edited 2010

Last edited 2010

Last edited 2010


shinkiro1(Posted 2010) [#2]
As soon as a Method becomes Abstract the whole Type becomes Abstract.
Therefore GraphicalObject is Abstract and there cannot be an instance (new object) created from it.

Defining a Method Abstract means the Extended Type has to implent such a Method itself (your Circle, Box, etc all have to implent their own Draw(..) Method).
Forcing an Extended Type to have it's own Draw(..) Method is because every Extended Type has another Drawing Routine( DrawCircle, DrawRect, DrawImage, etc ).
When not defining a Method Abstract, the Extended Types can use the Methods from the Extended Type (and don't have to implent their own).

In your Example the GraphicalObject is abstract due to its Abstract Method Draw(..). You can still define the GraphicalObject Abstract (that would be to help yourself when reading code and immediately see that this Type is Abstract).

Hope that helps a bit :D

Last edited 2010


jankupila(Posted 2010) [#3]
Thanks a lot. I had to use my dictionary but I think I understood what you ment.


shinkiro1(Posted 2010) [#4]
Sorry about that, I'll try to explain it with simpler words next time -.-


Czar Flavius(Posted 2010) [#5]
The reason you have a draw in GraphicalObject, which is empty, is so that you can put boxes, circles and texts into a list or array of GraphicalObject, and tell them to draw without knowing exactly what kind of GraphicalObject they are.

Anything which extends from GraphicalObject, will also take on its fields and methods. That's why you have x and y in GraphicalObject, to represent its position on the screen. Rather than setting up all the parameters of the object in loose code, you can tidy them up in Create methods. This shows a more feature-rich and expandable example.

Set a DebugStop at the beginning of the code, and go through line by line to see how it works.

Type GraphicalObject

    Field x:Float
    Field y:Float
    Field r:Int, g:Int, b:Int
    Field a:Float
    
    'all graphical objects automatically set their colour and alpha
    Method Draw(off_x:Float = 0, off_y:Float = 0) Final
        SetColor r, g, b
        SetAlpha a
        'we also manage the offset here too
        SubDraw(x + off_x, y + off_y)
        SetColor 255, 255, 255
        SetAlpha 1.0
    End Method
    
    'once the colour and alpha is set up, what to actually draw is up to them
    Method SubDraw(x:Float, y:Float) Abstract
    
    Method CreateMain:GraphicalObject(nx:Float, ny:Float, nr:Int, ng:Int, nb:Int, na:Float)
        x = nx 'x co-ordinate
        y = ny 'y co-ordinate
        r = nr 'red
        g = ng 'green
        b = nb 'blue
        a = na 'alpha transparency
        Return Self
    End Method

EndType

Type Circle Extends GraphicalObject

    Field r:Float
    
    Method SubDraw(x:Float, y:Float)
        DrawOval (x, y, r, r)
    EndMethod
    
    Method Create:circle(nr:Float)
        r = nr 'radius
        Return Self
    End Method

EndType

Type Box Extends GraphicalObject

    Field w:Float
    Field h:Float
    
    Method SubDraw(x:Float, y:Float)
        DrawRect(x, y, w, h)
    EndMethod
    
    Method Create:Box(nw:Float, nh:Float)
        w = nw 'width
        h = nh 'height
        Return Self
    End Method

EndType

Type Text Extends GraphicalObject

    Field text:String
    
    Method SubDraw(x:Float, y:Float)
        DrawText( Text, x, y)
    EndMethod
    
    Method Create:Text(ntext:String)
        Text = ntext 'text to display
        Return Self
    End Method
    
EndType

Graphics 640,480
'this is needed to turn ON alpha transparency
SetBlend(ALPHABLEND)

HideMouse

'we can store all objects to draw in one list
Local gobjects:TList = New TList

'we use both the CreateMain to set up position, colour and transparency
'and the unique Create method to set up parameters for each type of object  
gobjects.AddLast(New Box.Create(60, 20).CreateMain(0, 60, 0, 255, 255, 1.0))
gobjects.AddLast(New Box.Create(60, 20).CreateMain(100, 60, 0, 0, 255, 1.0))
gobjects.AddLast(New Circle.Create(20).CreateMain(20, 70, 255, 0, 0, 0.5))
gobjects.AddLast(New Circle.Create(20).CreateMain(120, 70, 255, 0, 0, 0.5))
gobjects.AddLast(New Text.Create("This is a test").CreateMain(0, 20, 255, 255, 0, 1.0))




While Not KeyHit(KEY_ESCAPE)
    Cls
    
    'although it takes a bit more work to set up, look how easy it is
    'to draw through all our objects. they could be circles, swords, castles
    'cars, planes, monsters, aliens, who cares! they can be drawn all like this
    For Local g:GraphicalObject = EachIn gobjects
        g.Draw()
    Next
    
    Flip
Wend


Last edited 2010


jankupila(Posted 2010) [#6]
"As soon as a Method becomes Abstract the whole Type becomes Abstract."

I have to disagree about that.
if you put sub1 in class1 abstract there comes a compile error because sub-type Class2 has not method "sub1". But now, when sub1 is not marked as abstract, program doesn't have compile-error.
So whole type is'nt abstract because sub1 is not abstract. I hope you understand what I mean.
SuperStrict

Type Class1
Field x:Int
Field y:Int
Field z:Int

Method sub1()
End Method 

Method sub2() Abstract
Method sub3() Abstract
End Type



Type Class2 Extends Class1

'Method sub1()
'End Method

Method sub2()
End Method

Method sub3()
End Method

End Type


Local blah:Class2=New Class2
blah.x=10
blah.y=10
blah.z=10
blah.sub1()
blah.sub2()
blah.sub3()




Jesse(Posted 2010) [#7]
a type with an abstract method or function in it forces the type to not be able to be instantiated as an independent type. That is, you can't do this:
type class1

method c1(n:int) abstract

method c2(d:int)
end method

end type

local ex:class1 = new class1


if you try to run the above code you will get an error because of the abstract method included in the type. the only way for it to work is to attach it to a type and include the proper declaration of the abstract method in the extended type. such as:
type class1

   method c1(n:int) abstract

   method c2(d:int)
   end method

end type

type class2 extends class1

  method c1(n:int)
      print n
  end method
end type

local ex:class2 = new class2
ex.c2()


in the above code the class1 can't be instantiated but the class2 can and class two can use the method c2 that is in class 1. In essense class1 type can be considered as abstract.


jankupila(Posted 2010) [#8]
But in class1 you don't call method c2 abstract so you can write program like that, don't using method c2 in Class2. Did I understand something wrong?

Edit: I looked your code again and now I understand what you ment. It's weird to play with methods in oop world because I don't understand everything yet. For eexample what sentence "Final" do?

Last edited 2010


Jesse(Posted 2010) [#9]
But you can't make an instance of class1 so that would make it useless by itself.


jankupila(Posted 2010) [#10]
I wouldn't call it useless if it has fields and methods what class2 uses.


Jesse(Posted 2010) [#11]
you edited the code and threw the conversation off sense I didn't read it.
what I meant is that it's useless if you never create an extention for it.

Last edited 2010


jankupila(Posted 2010) [#12]
Ok I see what you mean.


Jesse(Posted 2010) [#13]
of course you know that the whole type can be declared as abstract even if it does not have a single abstract function or method. right?:
type mytype abstract

  method c1()
  end method

  method c2()
  end method

end type


this type can only be instantiated through an extension.

Last edited 2010


Gabriel(Posted 2010) [#14]
For eexample what sentence "Final" do?

It prevents any classes(types) inheriting from this class(type).


jankupila(Posted 2010) [#15]
Thanks a lot!


jankupila(Posted 2010) [#16]
What means sentence "super"?


Jesse(Posted 2010) [#17]
that's how to access fields, methods and functions in the parent type from the extended type with the same name that exist in both types.
type entity
   field x:int
   
   method foo()
   .
   end method
end type

type myType extendes entity
    field x:int

    method foo()
      super.x = 25  ' assigns 25 to the x in the parent type
      super.foo()      ' calls the method in the parent type
   end method
end type

if super is not included for "super.foo()" then foo will call itself instead of calling the foo in the parent.


Czar Flavius(Posted 2010) [#18]
Type TDog
	Method identify()
		Print "I am a dog"
	End Method
End Type

Type TDalmation Extends TDog
	Method identify()
		Super.identify()
		Print "I am a dalmation"
	End Method
End Type

Type TGreyhound extends TDog
	Method identify()
		Super.identify()
		Print "I am a greyhound"
	End Method
End Type

New TDalmation.identify()
New TGreyhound.identify()


I am a dog

I am a dalmation

I am a dog

I am a greyhound