Enum/Enumerator in BMax (Types-basierend)
Übersicht

ShamanBetreff: Enum/Enumerator in BMax (Types-basierend) |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hallo.
Jeder von euch kennt sicher das Problem, dass BlitzMax keine Enums unterstützt. Dieses Problem wurde häufig dadurch umgangen, dass Enums durch Integer-Konstanten realisiert wurden. Mir hat diese Lösung nie ganz gefallen, desshalb hab ich mir ein anderes Enum-System überlegt: Dieses System basiert auf Types, es ist typsicher und unterstützt Standartfunktionen wie toString, fromName, u.s.w., wie aus andren Sprachen wie Java bekannt. Die Idee ist, dass das Enum ein Type ist, die Elemente des Enums sind Globale Felder mit Zeiger auf eine Instanz des Types. Somit wird immer ein Zeiger übergeben, und Zeiger verglichen. Da dieses System sehr schreibintensiv ist, hab ich eine Funktion geschrieben, die so ein Enum erstellt: Code: [AUSKLAPPEN] Function BuildEnum:String(name:String, enums:String[], withID:Int = 1, withName:Int = 1, withToString:Int = 1, generateDoc:Int = 1, autoInit:Int = 1) Local file:String = "'This file was built with EnumBuilder ~n'made by Shaman~n" 'Write Header If generateDoc = 1 Then file:+"Rem~n" file:+"~tbbdoc: Enumerator " + name + "~n" file:+"End Rem~n" End If file:+"Type " + name + "~n~n" Local i:Int 'Write Constants For i = 0 Until enums.Length If generateDoc = 1 Then file:+"~tRem~n" file:+"~t~tbbdoc: Enumerator item " + enums[i] + "~n" file:+"~tEnd Rem~n" End If file:+"~tGlobal " + enums[i] + ":" + name + "~n" Next file:+"~n" 'Write ID If withID = 1 Then file:+"~t'Enum items have an ID~n" file:+"~tField _id:Int~n" If generateDoc = 1 Then file:+"~tRem~n" file:+"~t~tbbdoc: Returns the ID of the enum item~n" file:+"~tEnd Rem~n" EndIf file:+"~tMethod getID:Int()~n" file:+"~t~tReturn Self._id~n" file:+"~tEnd Method~n~n" End If 'Write Names If withName = 1 Then file:+"~t'Enum items have a name~n" file:+"~tField _name:String~n" If generateDoc = 1 Then file:+"~tRem~n" file:+"~t~tbbdoc: Returns the name of the enum item~n" file:+"~tEnd Rem~n" EndIf file:+"~tMethod getName:String()~n" file:+"~t~tReturn Self._name~n" file:+"~tEnd Method~n~n" End If 'Write toString If withToString = 1 And withName = 1 Then file:+"~t'Overloaded toString() - Method~n" file:+"~tConst ENUM_NAME:String = " + Chr(34) + name + Chr(34) + "~n" If generateDoc = 1 Then file:+"~tRem~n" file:+"~t~tbbdoc: Returns the enum name followed by the item name~n" file:+"~t~tabout: Example return: " + name + "." + enums[0] + "~n" file:+"~tEnd Rem~n" End If file:+"~tMethod toString:String()~n" file:+"~t~tReturn " + name + ".ENUM_NAME + " + Chr(34) + "." + Chr(34) + " + Self._name~n" file:+"~tEnd Method~n~n" End If 'Generate Function FromID If withID = 1 Then file:+"~t'Gets the enum element by its ID, opposite of getID()~n" If generateDoc = 1 Then file:+"~tRem~n" file:+"~t~tbbdoc: Returns an element of the enum by its ID~n" file:+"~t~tabout: That's the opposite of getID()~n" file:+"~tEnd Rem~n" End If file:+"~tFunction FromID:" + name + "(id:Int)~n" file:+"~t~tSelect id~n" For i = 0 Until enums.Length file:+"~t~t~tCase " + (i + 1) + " Return " + name + "." + enums[i] + "~n" Next file:+"~t~t~tDefault Return Null~n" file:+"~t~tEnd Select~n" file:+"~tEnd Function~n~n" End If 'generate Function FromName If withName = 1 Then file:+"~t'Gets the enum element by its name, opposite of getName()~n" If generateDoc = 1 Then file:+"~tRem~n" file:+"~t~tbbdoc: Returns an element of the enum by its Name~n" file:+"~t~tabout: Opposite of getName()~n" file:+"~tEnd Rem~n" End If file:+"~tFunction FromName:" + name + "(name:String)~n" file:+"~t~tSelect name~n" For i = 0 Until enums.Length file:+"~t~t~tCase " + Chr(34) + enums[i] + Chr(34) + " Return " + name + "." + enums[i] + "~n" Next file:+"~t~t~tDefault Return Null~n" file:+"~t~tEnd Select~n" file:+"~tEnd Function~n~n" End If Local both:Int = 0 If withID = 1 And withName = 1 Then both = 1 file:+"~t'Create Function for less code~n" file:+"~tFunction Create:" + name + "(id:Int,name:String)~n" file:+"~t~tLocal e:" + name + " = new " + name + "~n" file:+"~t~te._id = id~n" file:+"~t~te._name = name~n" file:+"~t~tReturn e~n" file:+"~tEnd Function~n~n" End If 'Write Init file:+"~tFunction init()~n" For i = 0 Until enums.Length If both = 0 Then file:+"~t~t" + name + "." + enums[i] + " = new " + name + "~n" If withID = 1 Then file:+"~t~t" + name + "." + enums[i] + "._id = " + (i + 1) + "~n" End If If withName = 1 Then file:+"~t~t" + name + "." + enums[i] + "._name = " + Chr(34) + enums[i] + Chr(34) + "~n" EndIf Else file:+"~t~t" + name + "." + enums[i] + " = " + name + ".Create(" + (i + 1) + ", " + Chr(34) + enums[i] + Chr(34) + ")~n" EndIf Next file:+"~tEnd Function~n" 'Write End file:+"End Type~n" 'Write auto init If autoInit = 1 Then file:+"~n'automatically initialized~n" file:+name + ".init()" End If Return file End Function Sie liefert einen String zurück welcher, direkt in eine Datei geschrieben, die fertige BMX-Datei enthält. Ein Beispiel: Der Code: Code: [AUSKLAPPEN] Local testEnum:String[] = ["A", "B", "C", "D", "E", "F"] Local s:String = BuildEnum("TTestEnum", testEnum) Print s erzeugt ein Enum mit den Elenenten A,B,C,D,E und F. der erzeugte Code ist: Code: [AUSKLAPPEN] 'This file was built with EnumBuilder 'made by Shaman Rem bbdoc: Enumerator TTestEnum End Rem Type TTestEnum Rem bbdoc: Enumerator item A End Rem Global A:TTestEnum Rem bbdoc: Enumerator item B End Rem Global B:TTestEnum Rem bbdoc: Enumerator item C End Rem Global C:TTestEnum Rem bbdoc: Enumerator item D End Rem Global D:TTestEnum Rem bbdoc: Enumerator item E End Rem Global E:TTestEnum Rem bbdoc: Enumerator item F End Rem Global F:TTestEnum 'Enum items have an ID Field _id:Int Rem bbdoc: Returns the ID of the enum item End Rem Method getID:Int() Return Self._id End Method 'Enum items have a name Field _name:String Rem bbdoc: Returns the name of the enum item End Rem Method getName:String() Return Self._name End Method 'Overloaded toString() - Method Const ENUM_NAME:String = "TTestEnum" Rem bbdoc: Returns the enum name followed by the item name about: Example return: TTestEnum.A End Rem Method toString:String() Return TTestEnum.ENUM_NAME + "." + Self._name End Method 'Gets the enum element by its ID, opposite of getID() Rem bbdoc: Returns an element of the enum by its ID about: That's the opposite of getID() End Rem Function FromID:TTestEnum(id:Int) Select id Case 1 Return TTestEnum.A Case 2 Return TTestEnum.B Case 3 Return TTestEnum.C Case 4 Return TTestEnum.D Case 5 Return TTestEnum.E Case 6 Return TTestEnum.F Default Return Null End Select End Function 'Gets the enum element by its name, opposite of getName() Rem bbdoc: Returns an element of the enum by its Name about: Opposite of getName() End Rem Function FromName:TTestEnum(name:String) Select name Case "A" Return TTestEnum.A Case "B" Return TTestEnum.B Case "C" Return TTestEnum.C Case "D" Return TTestEnum.D Case "E" Return TTestEnum.E Case "F" Return TTestEnum.F Default Return Null End Select End Function 'Create Function for less code Function Create:TTestEnum(id:Int,name:String) Local e:TTestEnum = new TTestEnum e._id = id e._name = name Return e End Function Function init() TTestEnum.A = TTestEnum.Create(1, "A") TTestEnum.B = TTestEnum.Create(2, "B") TTestEnum.C = TTestEnum.Create(3, "C") TTestEnum.D = TTestEnum.Create(4, "D") TTestEnum.E = TTestEnum.Create(5, "E") TTestEnum.F = TTestEnum.Create(6, "F") End Function End Type 'automatically initialized TTestEnum.init() Dies kann z.B. so verwendet werden: Code: [AUSKLAPPEN] Local enum:TTestEnum enum = TTestEnum.B if enum = TTestEnum.C Then Print "enum ist B" Print "Name: "+enum.getName() enum = TTestEnum.FromName("D") 'gibt das element zurück, welches D repräsentiert Print "ID des Enums: "+enum.getID() Ein Wort zur Geschwindigkeit und Speicher: Geschwindigkeit ist die gleiche wie Enums mit Integern (auch Vergleiche) Nur wird ein wenig Speicher beim Initialisieren gebraucht. Dann in der Verwendung ist der Speicher der gleiche wie bei Integer. Anregung, Kritik erwünscht. |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group