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?

Code: BASIC
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::

Code: BASIC
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.

_______________

Code: BASIC
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