Structs with Methods

Started by _PJ_, April 29, 2024, 14:09:30

Previous topic - Next topic

_PJ_

Methods are apparently valid within structs:


I am guessing this is because under the hood, they are essentially just a special case of custom type

Maybe the "New" override in this example is also overriding some critical New() definition used for Struct types?
So am I right in thinking this is not really a good nor encouraged practice -
OR
Is there some fancy potential with this?

__
You may be wondering why don't I just use a Type - well, it's because in my actual use case, it's a very brief scope and I will not need huge numbers of these structs to be retained in memory or lists.

__
I found this thread:
https://archive.blitzcoder.org/forums/bmx-ng/106690.html#bottom

But I honestly did not fully understand so was unsur3 if this kind of usage would leak memory or not?

Struct SDATE
Field Year:Int
Field Month:Int
Field Day:Int

Method New(D:Int=0,M:Int=0,Y:Int=-1)
If Y=-1 Then Y=Int(CurrentDate("%Y"))
Self.Day=D
Self.Month=M
Self.Year=Y
End Method

Method Show:String()
Return Day+"-"+Month+"-"+Year
End Method
End Struct

Local D:SDATE = New SDATE
Print D.Show()


Derron

Having the overloaded New() is the way to go - especially if you create immutable structs (create them once and do not alter their "field values" anymore, and making the fields "readonly").


bye
Ron

_PJ_

Quote from: Derron on April 29, 2024, 14:48:17Having the overloaded New() is the way to go - especially if you create immutable structs (create them once and do not alter their "field values" anymore, and making the fields "readonly").


bye
Ron

That's excellent to hear. In my use case the fields are completely static so that's not an issue!
Thanks, Ron!

_PJ_

Took me a while to figure out just where to put "ReadOnly" in the declaration syntax :D

So in case anyone else needs to know::

Struct MyStruct
 Field ReadOnly MyStaticVar1:Int
 Field ReadOnly MyStaticVar2:Int

 Method New(v1:Int, v2:Int)
  Self.MyStaticVar1 = v1
  Self.MyStaticVar2 = v2
 End Method
End Struct

_PJ_

Just in case anyone finds this useful, I have expanded the SDATE Struct to accommodate some useful comparison operators, and named methods to make it more inline with 'typical' BMax syntax.

I know the "format" aspect of the ToString() is quite messy, I'm sure there are better ways to accomplish this, but it was a quick addition and is at least bare-bones functional.

_______________

Struct SDate
Field ReadOnly Year:Int
Field ReadOnly Month:Int
Field ReadOnly Day:Int

Method New(Y:Int,M:Int,D:Int)
Self.Year = Y
Self.Month = M
Self.Day = D
End Method

Method Operator=:Byte(date:SDate)
Return ((date.Year=Self.Year)*(date.Month=Self.Month)*(date.Day=Self.Day))
End Method

Method Operator<>:Byte(date:SDate)
Return Not(Self=date)
End Method

Method Operator>=:Byte(date:SDate)
Return (Self>date)|(Self=date)
End Method

Method Operator<=:Byte(date:SDate)
Return (Self<date)|(Self=date)
End Method

Method Operator>:Byte(date:SDate)
If (date.Year<Self.Year) Then Return True
If (date.Year=Self.Year)
If (date.Month<Self.Month) Then Return True
If (date.Month=Self.Month)
If (date.Day<Self.Day) Then Return True
End If
End If

Return False
End Method

Method Operator<:Byte(date:SDate)
If (date.Year>Self.Year) Then Return True
If (date.Year=Self.Year)
If (date.Month>Self.Month) Then Return True
If (date.Month=Self.Month)
If (date.Day>Self.Day) Then Return True
End If
End If

Return False
End Method

Method Min:SDate(date:SDate)
If (date.Year<Self.Year) Then Return New SDate(date.Year,date.Month,date.Day)
If (date.Year=Self.Year)
If (date.Month<Self.Month) Then Return New SDate(date.Year,date.Month,date.Day)
If (date.Month=Self.Month)
If (date.Day<Self.Day) Then Return New SDate(date.Year,date.Month,date.Day)
End If
End If

Return New SDate(Self.Year,Self.Month,Self.Day)
End Method

Method Max:SDate(date:SDate)
If (date.Year>Self.Year) Then Return New SDate(date.Year,date.Month,date.Day)
If (date.Year=Self.Year)
If (date.Month>Self.Month) Then Return New SDate(date.Year,date.Month,date.Day)
If (date.Month=Self.Month)
If (date.Day>Self.Day) Then Return New SDate(date.Year,date.Month,date.Day)
End If
End If

Return New SDate(Self.Year,Self.Month,Self.Day)
End Method


Method ToString:String(format:String="YYYY-MM-DD")
'formats are YYYY, YY, MM, M, DD, D
'with separator of "-"," "or"/"

format=Lower(format)
'defaults
Local pY:String="0000"
Local dY:String=Self.Year

Local pM:String="00"
Local dM:String=Self.Month

Local pD:String="00"
Local dd:String=Self.Day

Local bYM:String="-"
Local bMD:String="-"

If (Instr(format,"yyyy"))
' pY="0000"
' dY=Self.Year
Else
If (Instr(format,"yy"))
pY="00"
dY=Right(Self.Year,2)
End If
End If

If Instr(format,"mm")
pM="00"
' dM=Self.Month
Else
If Instr(format,"m")
pM="0"
' dM=Self.Month
End If
End If

If Instr(format,"dd")
' pD="00"
' dD=Self.Day
Else
If Instr(format,"d")
pD="0"
' dD=Self.Day
End If
End If

Local ymSep:String = Mid(format,Len(pY)+1,1)
Local mdSep:String = Mid(format,Len(pY)+1+Len(PM)+Len(Self.Month)+1,1)

If (Not(Instr("|-\/ ",ymsep)))
ymSep=bYM
End If
If (Not(Instr("|-\/ ",mdsep)))
mdSep=bMD
End If

Return Right(pY+Self.Year,Len(pY))+ymSep+Right(pM+Self.Month,Len(pM))+mdSep+Right(pD+Self.Day,Len(pD))
End Method
End Struct