Can a Class return a value like a function?

  1. ‹ Older
  2. 2 weeks ago

    Norman P

    Jul 3 Pre-Release Testers, Xojo Pro www.great-white-software.com/b...

    ParamArray with pairs might left you "fake" named parameters easier

    Private Sub Foo(ParamArray values as Pair)
      TextArea1.AppendText CurrentMethodName + " called" + EndOfLine
      
      For i As Integer = 0 To values.ubound
        
        TextArea1.AppendText Str(values(i).Left) + " = [ " + Str(values(i).Right) + "]" + EndOfLine
        
      Next
      
      TextArea1.AppendText "==========================================" + EndOfLine
      
    End Sub

    can be called like

    Foo
    Foo( "a" : 123  )
    Foo( "a" : 123  ,  "b" : 345 )
    Foo( "b" : 345  ,  "a" : 123  )

    but again INSIDE the method you have to do all the work to grab the named parameters and use them as appropriate

  3. jim m

    Jul 3 Pre-Release Testers, Xojo Pro piDog.com

    Assuming action returns an integer....

    Function Operator_Convert As Integer
      Return self.action
    End Function

    But as Norman said, there are probably better ways. operator_convert could lead to confusing code down the road.

    You could also consider a class that just holds the parameters/defaults and a function/functions that take that class as the argument.

    DIM args AS NEW FnArgs
    args.a = 123
    args.b = 234
    args.c = 345
    args.d = 456
    args.e = 567
    Result = Fn(args)
  4. Norman P

    Jul 3 Pre-Release Testers, Xojo Pro www.great-white-software.com/b...

    Jims suggestion of a parameter class is a good one as well

  5. @jim m You could also consider a class that just holds the parameters/defaults and a function/functions that take that class as the argument.

    I had already tried that. It works, but it is messy, in that now I need a companion class for every method. Better to embed the method into the class, as I explained near the top of this thread.

    What I really want is to be able to declare Properties within a Method, so then I could do the original code I want:

    DIM f AS NEW Fn
    f.a = 123
    f.b = 234
    f.c = 345
    f.d = 456
    f.e = 567
    Result = f
  6. jim m

    Jul 3 Pre-Release Testers, Xojo Pro piDog.com
    Edited 2 weeks ago

    Then you'll want to add the Operator_Convert function to the class.

    Function Operator_Convert As Integer
      Return self.action
    End Function

    It's just a regular method. Xojo recognizes the name and allows you to assign the class as if it was the return type. The method is called to make the assignment.
    Then you have the "Result = f" style you want.

  7. Kem T

    Jul 3 Pre-Release Testers, Xojo Pro, XDC Speakers Connecticut

    Also, Operator_Lookup will sort of let you do that, you would just put a Dictionary behind it.

  8. Edited 2 weeks ago

    @jim m Then you'll want to add the Operator_Convert function to the class.

    Jim: Can you tell me what I'm doing wrong?

    Window1 has TextField_A and TextField_B that I enter numbers into
    TextField_Result is the result of the Action Method under the Product Class

    Within the Window1

    Sub PushButton_Action() Handles Action
    DIM p AS NEW Product
    p.A = Val (TextField_A.Text)
    p.B = Val (TextField_B.Text)
    TextField_Result.Text = Str (p)
    End Sub

    Within the Product Class:

    Public Function Action() as Integer
    RETURN Self.A * Self.B
    End Function

    Public Function Operator_Convert() as INTEGER
    Return Self.Action
    End Function

    When I run it, I get the following compiler errors

    Window1.PushButton1.Action, line 4
    There is more than one item with this name and it's not clear to which this refers.
    TextField_Result.Text = Str (p)

    Window1.PushButton1.Action, line 4
    Type mismatch error. Expected String, but got Int32
    TextField_Result.Text = Str (p)

    What am I doing wrong?

    EDIT: Corrected Function Action() As Integer

  9. I don't understand it, but this works:

    DIM p AS NEW Product
    p.A = Val (TextField_A.Text)
    p.B = Val (TextField_B.Text)
    DIM Result as INTEGER = p
    TextField_Result.Text = Str (Result)

    Whereas this does not work:

    DIM p AS NEW Product
    p.A = Val (TextField_A.Text)
    p.B = Val (TextField_B.Text)
    TextField_Result.Text = Str (p)
  10. Kem T

    Jul 3 Pre-Release Testers, Xojo Pro, XDC Speakers Connecticut

    Sounds like the compiler isn't as smart as you'd hope. What if you do p+0 instead?

  11. Window1.PushButton1.Action, line 5
    Undefined operator. Type Product does not define "Operator_Add" with type Int32
    TextField_Result.Text = Str (p+0)

  12. jim m

    Jul 3 Pre-Release Testers, Xojo Pro piDog.com
    Edited 2 weeks ago

    str() doesn't give the compiler enough clues. It could take any number type, or a date, a color etc...
    Add another Operator_lookup and you don't even need str()

    Function Operator_Convert As String
      Return str(self.action)
    End Function
  13. In this particular case, it is str, but I wait to make the function generic so the calling routine can do anything with the return value. Is there a way to force the Operator_Convert to always return an integer?

  14. Kem T

    Jul 3 Pre-Release Testers, Xojo Pro, XDC Speakers Connecticut

    Or forget Operator_Convert and just add a Result (or similar) function or Computed Property (useful for debugging).

  15. jim m

    Jul 3 Pre-Release Testers, Xojo Pro piDog.com
    Edited 2 weeks ago

    I would go with what @Kem T suggests

    You can also use ctype if you really want to
    TextField_Result.Text = Str (ctype(p,integer))

    But honestly, I would rethink this... I'm thinking of a future situation where you store the class in an integer property and then the instance goes out of scope because you've only stored the result rather than the instance...

    using a .result computed property is a very good suggestion.

  16. I'm missing something. Instead of a .result computed property, I should just use a result method, as I posted originally in this thread (I called it . Action)

  17. jim m

    Jul 3 Pre-Release Testers, Xojo Pro piDog.com

    The idea of using a computed property is so that when you are looking at the debugger values pane, you'll see the value. If it is a method, you don't see it in the debugger.

  18. Kem T

    Jul 3 Pre-Release Testers, Xojo Pro, XDC Speakers Connecticut

    What Jim said. There are some other differences like a method can be overridden whereas a property will be shadowed, but will otherwise perform the same function in this context.

  19. Thanks for the clarification - that was a subtlety that eluded me.

  20. James D

    Jul 4 Pre-Release Testers, Xojo Pro Europe (Switzerland)

    Well, I don't think it is a great idea to start using dictionaries as method parameters because you loose a lot of the type checking, auto complete, help tips etc.....

    But if you are going to do it and you want to make it look pretty and more legible then I'd suggest you create a class which encapsulates the dictionary and have that class implement the Operator_Lookup operator. You could then write code like:

    Dim items As New MyParamsList
    
    items.X = 1
    items.Name = "Jim"
    items.MyFolder = SpecialFolder.Documents
    
    Call MyFuncX(items)
    
    Dim newItems As NewParamsList
    
    newItems.Y = "ABC"
    newItems.MyColor = Color.Red
    
    Call MyOtherFunc(newItems)

    You still will loose out on the auto complete and help prompts. The example code below shows you how to do this.

    Sub Operator_Lookup(key As String, Assigns value As Variant)
      //--------------------------------------------------------------------------------
      //  Sets or updates the value for a property
      //
      Dim actualKey As String = PropertyToKey(key)
      Dim item As SetupItemBase
      
      If mList.HasKey(actualKey) Then
        item = SetupItemBase(mList.Value(actualKey))
        item.Value = value
        
        Return
      End If
      
      Dim type As Integer = VarType(value)
      
      Select Case type
      Case 2, 3
        item = New IntegerSetupItem(actualKey, value)
      Case 4
        item = New SingleSetupItem(actualKey, value)
      Case 5
        item = New DoubleSetupItem(actualKey, value)
      Case 6
        item = New CurrencySetupItem(actualKey, value)
      Case 7
        item = New DateSetupItem(actualKey, value)
      Case 8
        item = New StringSetupItem(actualKey, value)
      Case 9
        item = New FolderItemSetupItem(actualKey, value)
      Case 11
        item = New BooleanSetupItem(actualKey, value)
      Case 16
        item = New ColorSetupItem(actualKey, value)
      Case Else
        SetupException_AS.Throw(kError_DataTypeNotSupported + Str(type))
      End Select
      
      mList.Value(actualKey) = item
    End Sub
    Function Operator_Lookup(key As String, Optional value As Variant) As Variant
      //--------------------------------------------------------------------------------
      //  Returns the value of the property, with an optional 
      //  default
      //
      Dim actualKey As string = PropertyToKey(key)
      Dim item As SetupItemBase
      
      If mList.HasKey(actualKey) Then
        item = SetupItemBase(mList.Value(actualKey))
        Return item.Value
      End If
      
      Return value
    End Function
  21. Edited 2 weeks ago

    Thanks to all who helped out. I tried both the Dictionary method and the Class method with a Class.Result function that returns the result. I was not concerned about the Calculated Property because I use a system log that reports the returned value of functions (substantially better than breakpoints).

    In the end, I chose the Class method, because I also define Constants within the Class that I can use as Integer Enumerators, as in Class.Property = Class.Constant. It makes the code very clean and easy to use, especially with IDE type look-ahead for both property and constant names within the class.

or Sign Up to reply!