Abstract
BlitzMax Forums/BlitzMax Beginners Area/Abstract
| ||
What's the use of Abstract? As there is no real need to define a method or function in the base object, you still have to redefine it in the extended type. Also if you have a create function, the extended type won't be created unless you have a create function for the extended type. |
| ||
What's the use of Abstract? You use Abstract to define a methods interface. Since Abstract methods must be implemented in any concrete class (that is, a class that is instanced), you can invoke the Abstract methods safely. |
| ||
The point of Abstract is that you saying that you are not allowed to directly create the type in question but that any child types must implement all abstract methods exactly as you have defined them. So if we take a quick example lets say that we need a number of different bullets in our game, to keep it simple they all work the same way but they render differently. The first step would be to define a base bullet type like so... Type Bullet Field x:Float = 0 Field y:Float = 0 Field dX:Float = 0.1 Field dY:Float = 0 Method setPosition(newX:Float, newY:Float) x = newX y = newY End Method Method update () x = x + dX y = y + dY End Method Method render () Abstract End Type This type would define all the shared functionality that each bullet needs and also defines what you could describe as an interface that we know will exist in any child type, in this example the render() method. So now we would define all our child types like so... Type SimpleBullet Extends Bullet Method render() DrawOval(x, y, 10, 5) End Method End Type Type BlockBullet Extends Bullet Method render() DrawRect(x, y, 5, 5) End Method End Type So now we have our bullets defined and we know exactly what methods are available to us. So in our project we can define the variables like so... Local b1:Bullet = New SimpleBullet Local b2:Bullet = New SimpleBullet Local b3:Bullet = New BlockBullet Local b4:Bullet = New BlockBullet b1.render() b2.render() b3.render() b4.render() Now because we have defined the abstract render method we do not get the "Identifier 'render' not found" message when we try to compile the project. As for a create function if really depends on what exactly is required to be done when each of the different types are created. But lets say that all of our bullets are created in the same way and that they will all be created from the base Bullet type with a create method. The step do do this are: 1. Create the method and define the return type as Bullet. This will allow us to return any child type. 2. Check what type of bullet we want and create it. 3. Configure the new bullet and return. Therefore you could do something like... Type Bullet '... Existing Bullet type code above here ... Function create:Bullet(what:String, newX:Float, newY:Float) Local b:Bullet Select what Case "block" b = New BlockBullet Case "simple" b = New SimpleBullet Default RuntimeError("Invalid bullet type specified.") End Select b.setPosition(newX, newY) Return b End Function End Type Which we could then use like so... Local b1:Bullet = Bullet.create("simple", 10, 10) Local b2:Bullet = Bullet.create("simple", 10, 10) Local b3:Bullet = Bullet.create("block", 10, 10) Local b4:Bullet = Bullet.create("block", 10, 10) b1.render() b2.render() b3.render() b4.render() As you should be able to see you can now create any bullet type you like and not really have to worry about it in other parts of you code as all you will be specifying is that it is a bullet and because of the abstract methods each bullet type can work differently internally but on the outside they are all exactly the same freeing you from having to constantly code around all the different bullet types in your project. I hope this helps. :) |
| ||
FYI. A little example...Type Bullet Field x:Float = 0 Field y:Float = 0 Field dX:Float = 1.0 Field dY:Float = 0.5 Method setPosition(newX:Float, newY:Float) x = newX y = newY End Method Method update () x = x + dX y = y + dY End Method Method render () Abstract Function create:Bullet(what:String, newX:Float, newY:Float) Local b:Bullet Select what Case "block" b = New BlockBullet Case "simple" b = New SimpleBullet Default RuntimeError("Invalid bullet type specified.") End Select b.setPosition(newX, newY) Return b End Function End Type Type SimpleBullet Extends Bullet Method render() Print("o ("+x+","+y+")") End Method End Type Type BlockBullet Extends Bullet Method render() Print("= ("+x+","+y+")") End Method End Type Local b1:Bullet = Bullet.create("simple", 10, 10) Local b2:Bullet = Bullet.create("simple", 10, 100) Local b3:Bullet = Bullet.create("block", 200, 10) Local b4:Bullet = Bullet.create("block", 10, 20) b1.render() b2.render() b3.render() b4.render() Print("++++++++++++++++++++") b1.update() b2.update() b3.update() b4.update() b1.render() b2.render() b3.render() b4.render() |
| ||
Well, thank you very much, this helps greatly. @Lomat,, Great code, simple and to the point. This will help me a lot, specialy the create bit. I hadn't realized that methods would accept parametres. So if I am not confused methods seem to be confined to the element(s) in the type, and functions to the type itself. Odd this OOP business, seems more difficult to explain than to understand. |
| ||
Type methods act on an instance of a type. e.g. Local b:Bullet = new SimpleBullet b.myMethod() Type functions are static, i.e. you can call/use them anywhere and they are not linked to any instance of that type. Bullet.myFunction() |
| ||
Hello. 7 fish. Goodbye. |
| ||
That was excellent, Lomat. Anyone who asks from now on should be directed here. |
| ||
Great explanation! Why not include somewhere in the wiki? could be a good reference for beginners |