Announcement

Collapse
No announcement yet.

Method End Method Statements

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Method End Method Statements

    Please add your comments and suggestions as a Reply to this thread.





    PB/WIN - METHOD/END METHOD statements

    Purpose
    Define a METHOD procedure within a class.
    Syntax
    [CLASS|OVERRIDE] METHOD name [<DispID>] [ALIAS "altname"] (var AS type...) [THREADSAFE] [AS type]
    [statements]
    METHOD = expression
    END METHOD
    Remarks
    METHOD/END METHOD is used to define a METHOD procedure within a class. Standard methods can only be called through a virtual function table on a valid object.

    A METHOD is a block of code, very similar to a user-defined function. Optionally, it can return a value, like a FUNCTION, or merely act as a subroutine, like a SUB. If the optional "AS type" is included, the method returns a value set by "Methodexpr", or defaults to a return value of zero (0) or nul string, depending upon the type. METHOD parameters may be any variable type, including VARIANT variables. Methods may be called using any of the five following forms:

    Code:
    DIM ObjVar AS MyInterface
    LET ObjVar  = NEWCOM Prgid$
    1. ObjVar.Method1(param)
    2. CALL ObjVar.Method1(param)
    3. ObjVar.Method1(param) TO var
    4. CALL ObjVar.Method1(param) TO var
    5. var = ObjVar.Method1(param)
    Forms 1 and 2 assume that the Method does not return a value, or you simply wish to discard it. Forms 3, 4, and 5 require that the Method return a value compatible with the type of variable specified as var. Parentheses enclosing parameters are optional in forms 1 and 3.

    Methods may be declared (using AS type...) to return a string, any of the numeric types, a specific class of object variable (AS MyClass), a Variant, or a user defined Type.
    Type Libraries only support the following data types: BYTE, WORD, DWORD, INTEGER, LONG, QUAD, SINGLE, DOUBLE, CURRENCY, OBJECT, STRING, and VARIANT. If any Methods or Properties use data types not supported by Type Libraries, you will receive a Error 581 - Type Library creation error, when using the #COM TLIB ON metastatement.
    In addition to the explicit return value which you declare, all Methods and Properties on an IAutomation or IDispatch interface have another "Hidden Return Value", which is cryptically named hResult. While the name would imply a handle for a result, it's really not a handle at all, but just a long integer value, used to indicate success or failure of the Method. After calling a Method or Property, you can retrieve the hResult value with the PowerBASIC function OBJRESULT. The most significant bit of the value is known as the severity bit. That bit is 0 (value is positive) for success, or 1 (value is negative) for failure. The remaining bits are used to convey error codes and additional status information. If you call any object Method/Property (either Dispatch or Direct), and the severity bit of hResult is set, PowerBASIC generates INTERFACE blocks. This shows it is a direct member of the class, rather than a member of an interface.

    Code:
    CLASS MyClass
      INSTANCE MyVar AS LONG
      CLASS METHOD MyClassMethod(BYVAL param AS LONG) AS STRING
        METHOD = "My" + STR$(param + MyVar)
      END METHOD
      INTERFACE MyInterface
        INHERIT IUNKNOWN
        METHOD MyMethod()
          Result$ = ME.MyClassMethod(66)
        END METHOD
      END INTERFACE
    END CLASS
    In the above example, MyClassMethod() is a CLASS METHOD, and is always accessed using the pseudo-object ME (in this case ME.MyClassMethod). Class methods are never accessible from outside a class, nor are they ever described or published in a type library. By definition, there is no reason to have a private PROPERTY, so PowerBASIC does not offer a CLASS PROPERTY structure.

    Constructors and Destructors
    There are two special class methods which you may optionally add to a class. They meet a very specific need: automatic initialization when an object is created, and cleanup when an object is destroyed. Technically, they are known as constructor and destructor methods, and can perform almost any functionality needed by your object: initialization of variables, reading/writing data to/from disk, etc. You do not call these methods directly from your code. If they are present in your class, PowerBASIC automatically calls them each time an object of that class is created or destroyed. If you choose to use them, these special class methods must be named CREATE and DESTROY. They may take no parameters, and may not return a result. They are defined at the class level, so they may never appear within an INTERFACE definition.

    Code:
    CLASS MyClass
      INSTANCE MyVar AS LONG
      CLASS METHOD CREATE()
        ' Do initialization
      END METHOD
      CLASS METHOD Destroy()
        ' Do cleanup
      END METHOD
      INTERFACE MyInterface
        INHERIT IUNKNOWN
        METHOD MyMethod()
          ' Do things
        END METHOD
      END INTERFACE
    END CLASS
    As displayed above, CREATE and DESTROY must be placed at the class level, but outside of any interface block. You should note that it's not possible to name any standard method (one that's accessible through an interface) as CREATE or DESTROY. That's just to help you remember the rules for a constructor or destructor. However, you may use these names as needed to describe a method external to your program.

    A very important caution: You must never create an object of the current class in a CREATE method. To do so will cause CREATE to be executed again and again until all available memory is consumed. This is a fatal error, from which recovery is impossible.

    Override Methods
    You can add to, or replace, the functionality of a particular method or property of an inherited base class by coding a replacement which is preceded by the word OVERRIDE. The overriding method must have the same name and signature (parameters, return value, etc.) as the one it replaces.

    Dispatch ID
    Every method and property in a dual interface needs a positive, long integer value to identify it. That integer value is known as a DispID (Dispatch ID), and it's used internally by COM services to call the correct function on a Dispatch interface. You can optionally specify a particular DispID by enclosing it in angle brackets immediately following the Method/Property name:

    Code:
    METHOD  MethodOne <76> ()
    If you don't specify a DispID, PowerBASIC will assign a random value for you. This is fine for internal objects, but may cause a failure for published COM objects, as the DispID could change each time you compile your program. It is particularly important that you specify a DispID for each Method/Property in a COM Event Interface.

    BYREF and BYVAL attributes
    Just like a SUB or FUNCTION, PowerBASIC uses BYREF parameters as the default form, unless you specify a BYVAL override. Either key word can be placed before the parameter name, along with IN, OUT, and INOUT, as described later.
    BYVAL
    A copy of the data value is placed on the stack as a parameter. The copy is destroyed when the METHOD ends. BYVAL parameters default to an IN parameter, if no explicit direction is specified.
    BYREF
    A pointer to the data is placed on the stack as a parameter. If the data is a variable, any changes to the parameter are passed back to the caller in the variable. If the data is an expression, it is destroyed when the METHOD ends. BYREF parameters default to an INOUT parameter, if no explicit direction is specified.
    Direction attributes
    METHOD parameters may also specify the direction in which data is passed between the caller and callee:
    IN
    Data is passed from the caller to the METHOD. Generally speaking, you'll find that almost all IN parameters are passed BYVAL, and that is highly recommended. However, it is possible to pass them BYREF if necessary.
    OUT
    Data is passed from the METHOD back to the caller. All OUT parameters must be passed BYREF.
    INOUT
    Data is passed from the caller to the METHOD, and results are returned to the caller in the same parameter. All INOUT parameters must be passed BYREF.
    In many cases, the direction of a parameter can be inferred directly from the BYVAL/BYREF attribute (BYVAL=IN, BYREF=OUT). However, we recommend that you include the direction attribute as an added means of self-documentation. Each METHOD parameter name may be preceded by one of BYVAL/BYREF, and one of IN/OUT/INOUT, in any sequence.

    You should note an interesting rule of COM objects: IN parameters are read-only. They may not be altered.
    IN parameters are considered by COM rules to be "constant" which may not be altered, because they are values which are not returned to the caller. However, since this is not a rule normally applied to a standard SUB or FUNCTION, it can allow programming bugs which are most difficult to find and correct. For this reason, PowerBASIC automatically protects you from this issue with no action needed on your part. When writing METHOD or PROPERTY code in PowerBASIC, you may freely assign new values to BYVAL/IN parameters. They will simply be discarded when the METHOD exits. Of course, not every programming language protects you in this way, so you must use caution if you create a COM METHOD in another compiler.

    Using OPTIONAL/OPT
    METHOD statements may specify one or more parameters as optional by preceding the parameter with either the keyword OPTIONAL (or the abbreviation OPT). When a parameter is declared optional, all subsequent parameters in the declaration are optional as well, whether or not they specify an explicit OPTIONAL or OPT directive.

    VARIANT variables are particularly well suited for use as an optional parameter. If the calling code omits an optional VARIANT parameter, (BYVAL or BYREF), PowerBASIC (and most other compilers) substitute a variant of type %VT_ERROR which contains an error value of %DISP_E_PARAMNOTFOUND (&H80020004). In this case, you can check for this value directly, or use the ISMISSING function to determine whether the parameter was physically passed or not.

    When optional parameters (other than VARIANT) are omitted from the calling code, the stack area normally reserved for those parameters is zero-filled.

    If the parameter is defined as a BYVAL parameter, it will have the value zero. For TYPE or UNION variables passed BYVAL, the compiler will pass a string of binary zeroes of length SIZEOF (Type_or_union_var).

    If the parameter is defined as a BYREF parameter, VARPTR (Varname) will equal zero; when this is true, any attempt to use Varname in your code will result in a General Protection Fault or memory corruption. You should use the ISMISSING() function first to determine whether it is safe to access the parameter.

    THREADSAFE Option Descriptor
    If you include the option THREADSAFE, PowerBASIC automatically establishes a semaphore which allows only one thread to execute it at a time. Others must wait until the first thread exits the THREADSAFE procedure before they are allowed to begin.
    See AlsoReferences
    String:
    Numeric:
    BYREF:
    BYVAL:
    OPTIONAL:
    Thread:
    Last edited by Gary Beene; 28 Oct 2014, 09:52 PM.

  • #2
    Hi Gary,

    I am fairly new to Class creation in Powerbasic and I am reading all I can get both in the forums and in the help files.

    I am interested in passing parameters to an object when it is created, something similar to what can be done in C#.
    I read a very interesting post about Classes (http://www.powerbasic.com/support/pb...ad.php?t=50958) that talks about Class Factory Routines althoug and extra sub for initialization is needed.
    Otherwise in the "Method/End Method Statement" entry in the help file it can be read:

    "They may take no parameters, and may not return a result." in the "Constructors and Destructors" paragraph what as far I understand offers the possibility of doing something similar to what can be done in C#.

    I am not a native english speaker but I learned at the school is that "May" indicates possibility so if "It may take no parameters" that also means that "It can take parameters". Am I wrong? Did I misunderstand the text?

    If I am right and the class can accept parameters for the Create Method when the object is created it would be nice to give some example of the sintaxis as I have not been able to find any code that shows how to do that, maybe it is because it is not possible and then I suggest to clarify that statement.

    Thank you for your attention and keep up the good work.

    Best regards.

    Fran Dominguez

    Comment


    • #3
      I am not a native english speaker but I learned at the school is that "May" indicates possibility so if "It may take no parameters" that also means that "It can take parameters". Am I wrong? Did I misunderstand the text?
      They can't take parameters.
      Forum: http://www.jose.it-berater.org/smfforum/index.php

      Comment


      • #4
        Hi José,

        thanks for the clarification.

        It cannot accept parameters, crystal clear now.

        Then I'd suggest to change that paragraph from "may take no parameters" to "can't take parameters" in order to avoid confusion to beginners like me.

        Saludos,

        Fran

        Comment


        • #5
          I agree that a clarification is needed.
          "Not my circus, not my monkeys."

          Comment


          • #6
            PB classes are COM classes.

            A COM object is created with CoCreateInstance.

            CoCreateInstance is a wrapper function that calls CoGetClassObject to get a pointer to the IClassFactory interface and then calls the CreateInstance method of that interface.

            There is no way to pass custom parameters to these functions. You are not going to see any COM server that accepts parameters when you create an instance of an object. C++ and other OOP languages use a different kind of classes.
            Forum: http://www.jose.it-berater.org/smfforum/index.php

            Comment


            • #7
              José,

              your comment is very interesting because it sheds lights over the internal working of the Powerbasic classes.
              I am curious, How do you know what functions are called from Powerbasic when creating objects? Any specific tool to see that?

              Because PB clases works so different compared to C# and C++ classes this leads me to a new question.

              Suppose that I am going to use a class in a DLL that has been created in C++ and needs parameters when the object is instantiated.
              How can the object be created from Powerbasic if I cannot pass parameters?

              Is this a nosense question?

              Best regards.

              Fran

              Comment


              • #8
                Hi Eric,

                Originally posted by Eric Pearson View Post
                I agree that a clarification is needed.
                I continued reading the PB help file and in the "Error 587" entry, I can read:

                Invalid Constructor/Destructor - Constructor and Destructor Methods must be CLASS METHODS. They must take no parameters and return no result.

                I think there is a big difference between MAY and MUST so I bet "may" is a typo in the "Method/End Method Statement" entry in the help file what is confirmed by the José's clarification and the "Error 587" redaction.

                Native english speakers should have more to say than I about the proper verb to use there.

                Best regards.

                Fran

                Comment


                • #9
                  Originally posted by Fran Dominguez View Post

                  I think there is a big difference between MAY and MUST so I bet "may" is a typo in the "Method/End Method Statement" entry in the help file what is confirmed by the José's clarification and the "Error 587" redaction.

                  Native english speakers should have more to say than I about the proper verb to use there.
                  English does not always make sense.
                  In this case, may is negated entirely.
                  "May not" means it is not allowed, rather than is may or may not.
                  The wording is unclear, though it is proper English.
                  Where you see:
                  "They may take no parameters, and may not return a result."
                  You should read:
                  They do not take parameters and do not return results.
                  The world is strange and wonderful.*
                  I reserve the right to be horrifically wrong.
                  Please maintain a safe following distance.
                  *wonderful sold separately.

                  Comment


                  • #10
                    Hi Kurt,

                    Originally posted by Kurt Kuzba View Post
                    In this case, may is negated entirely.
                    "May not" means it is not allowed, rather than is may or may not.
                    The wording is unclear, though it is proper English.
                    Where you see:
                    "They may take no parameters, and may not return a result."
                    You should read:
                    They do not take parameters and do not return results.
                    I've learned something new, thanks.

                    It was no my intention to say it wasn't proper english.I simply suggest to use the most appropiate verb from the point of view of clarity.

                    Thanks for your comment.

                    Fran
                    Last edited by Fran Dominguez; 26 Nov 2014, 05:38 AM.

                    Comment


                    • #11
                      > I am curious, How do you know what functions are called from Powerbasic when creating objects? Any specific tool to see that?

                      It is the standard way specified by the COM technology. When you write a COM server, you have to implement the IClassFactory interface and export the function CoGetClassObject, that returns a pointer to that interface. Otherwise, the COM library will be unable to create an instance of it.
                      Forum: http://www.jose.it-berater.org/smfforum/index.php

                      Comment


                      • #12
                        Hi José,

                        once again thanks for your anwer.

                        Originally posted by José Roca View Post
                        It is the standard way specified by the COM technology. When you write a COM server, you have to implement the IClassFactory interface and export the function CoGetClassObject, that returns a pointer to that interface. Otherwise, the COM library will be unable to create an instance of it.
                        So, I shouldn't worry about someone to give me a DLL that needs to pass parameters when an object it instantiated. It is HIS bad programming practice, not mine not able to pass initialization parameters.

                        Then the good practice should be to create a kind of INIT method in the class to which I can pass parameters to be asigned to instance variables instead of trying to do that in the CREATE method. Right?

                        What are the advantages or reasons to pass parameters in C++ and C#? I mean, Why to do that if it is not the standard method?

                        I am so sorry to interrogate you so much. This forum is wonderful for someone like me that is not a programmer and wants to learn windows programming, For years VB4 has been hidden me from what was behind the scenes.

                        I always try to learn reading and searching for information instead of asking for help but so often there are things that I simply cannot learn by myself.

                        Best regards.

                        Fran

                        Comment


                        • #13
                          So, I shouldn't worry about someone to give me a DLL that needs to pass parameters when an object it instantiated. It is HIS bad programming practice, not mine not able to pass initialization parameters.
                          It's not a matter of good or bad practices. COM technology is a binary standard and the use of classes is not mandatory, just a convenience. The only language requirement for COM is that the code defining the COM be generated in a language that can create structures of pointers and either explicitly or implicitly, call functions through pointers. COM has well defined rules and you have to follow them, no matter which language you use. There are not COM servers, written in C++ or any other language, that allow to pass parameters when creating an instance of it. What happens is that some languages support the use of other kind of classes that don't use the COM technology. They are different animals.

                          What are the advantages or reasons to pass parameters in C++ and C#? I mean, Why to do that if it is not the standard method?
                          These classes are not specifically designed for COM programming, but for OOP (Object Oriented Programming), and follow their own rules. As they are not an standard, each language implements them its own way and its use is often incompatible with other languages. For example, you can use with PB a COM server written with C++, but not a library of C++ classes.

                          It is important to note that COM is not an object oriented language. It does not support OOP concepts such multiple inheritance, polymorphism, overloading, etc.

                          Then the good practice should be to create a kind of INIT method in the class to which I can pass parameters to be asigned to instance variables instead of trying to do that in the CREATE method. Right?
                          Right.
                          Forum: http://www.jose.it-berater.org/smfforum/index.php

                          Comment


                          • #14
                            Native english speakers should have more to say than I about the proper verb to use there
                            A native English speaker would say the PowerBASIC documentation is the wrong place to learn English.
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              José,

                              What a didactical post!!

                              Now it is clear for me that:

                              1) What can be done in C++ and C# passing parameters to an object constructor is OOP but no COM compliant.

                              2) PB (as I read somewhere besides in your post) is not OOP languaje but support COM programming.

                              3) PB does not accept parameters passed to an object when it is instantiated.

                              Well noted.


                              Michael,

                              >A native English speaker would say the PowerBASIC documentation is the wrong place to learn English.

                              Hahaha....British or American?

                              Jokes apart, learn how something shouldn't be done and the reasons for that is also learning...even more than learning how to do it without any reason.

                              Semantics is sometimes even more dificult than programming. Kurt said that "May not" means it is "not allowed" in this case, although my interpretation was different. He is an english speaker and I am not, so I learned that "May" not always indicates possibility.

                              Anyway I think all of us agree that it is more clear to use "CAN NOT", "MUST NOT", etc, to avoid any misunderstanding.


                              Thanks to everybody for your comments.

                              Best regards.

                              Fran

                              Comment


                              • #16
                                > He [Kurt] is an english speaker and I am not..

                                The jury is still out...

                                (We are allowed to tease fellow Cheddarheads!)
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Originally posted by Fran Dominguez View Post
                                  1) What can be done in C++ and C# passing parameters to an object constructor is OOP but no COM compliant.

                                  2) PB (as I read somewhere besides in your post) is not OOP languaje but support COM programming.

                                  3) PB does not accept parameters passed to an object when it is instantiated.
                                  Just a couple of additional thoughts.

                                  1) I haven't found any references that suggest passing parameters to a constructor is a hallmark of oop. I believe it's more of a convenience that several of the oop programming languages have.

                                  2) I would argue that PB is an OOP language. If the argument is that PB doesn't support all known OOP enhancements, the same argument could be made of C++. PB does support Encapsulation, Inheritance (limited), and Classes.

                                  3) Agreed. You can use constructor functions for this though. For example:
                                  Code:
                                   Sub NewTest( ByVal id As Long, ByRef obj As iTest  )
                                     obj = Class "cTest"
                                     obj.Id = id
                                   End Sub
                                   Class cTest
                                     Instance id_ as Long
                                     Interface iTest
                                       Inherits IUnknown
                                       Property Set Id( value as Long )
                                         id_ = value
                                       End Property
                                     End Interface
                                   End Class
                                  An initialization method in an Interface is another great way to set initial values at runtime.

                                  I believe that thinking of PB as an oop language that uses Interfaces as a method of polymorphism might change your opinion of it's "Object Orientedness". Look to the features that PB natively provides and how that can be leveraged.
                                  LarryC
                                  Website
                                  Sometimes life's a dream, sometimes it's a scream

                                  Comment


                                  • #18
                                    If you have created your PROPERTYs and METHODSs using the PB COM Browser, you should be aware that the COM Browser substitutes "AS LONG" for "AS BOOLEAN" without warning or error because PB has no BOOLEAN datatype.

                                    Some METHODs of interfaces - specifically the Microsoft Message Queue API ("MSMQ") require parameters of type BOOLEAN. In MSMQ, A parameter passed to this API "LONG" (that is, not BOOLEAN) is interpreted as "false" regardless of the value of the LONG.

                                    When this is the case you will need to create your own VARIANT of type VT_BOOLEAN (there is code in the forum to do this) to use the API.

                                    MCM
                                    Last edited by Michael Mattias; 16 Mar 2015, 12:05 PM.
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment

                                    Working...
                                    X