.Introduction (Code)

Category: Objects

Date: 02-16-2022

Return to Index


 
'**************************************************************
 
'CLASS BLOCK
Class MyClassName
End Class
 
'**************************************************************
 
'INTERFACE BLOCK
Class MyClassName
   Interface MyInterfaceName
   End Interface
End Class
 
'INTERFACE BLOCK  (a CLASS can have more than one INTERFACE BLOCK)
Class MyClassName
   Interface MyInterfaceNameA
   End Interface
   Interface MyInterfaceNameB
   End Interface
End Class
 
'**************************************************************
 
'A CLASS contains variable definitions and procedures.
'No code, other than variable definitions, exists outside a procedure
'Procedure consist of CLASS METHODS, METHODS, PROPERTY procedures
'A METHOD (no CLASS in front of it) is an INTERFACE METHOD
'CLASS METHODS are placed outside an INTERFACE BLOCK
'INTERFACE METHODS are placed inside an INTERFACE BLOCK
'PROPERTY procedures are placed inside an INTERFACE BLOCK
'PROPERTY procedures are a special type of METHOD procedures
'Procedures inside an INTERFACE BLOCK are exposed
'Procedure outside an INTERFACE BLOCK are hidden
'Variable definition, called INSTANCE variables, are defined outside an INTERFACE BLOCK
'INSTANCE variables cannot be accessed directly from outside the object
'PROPERTY procedure are used to expose INSTANCE variables
'PROPERTY procedures are only allowed inside an INTERFACE BLOCK
 
 
'NOTE: PowerBASIC does not use the terminology INTERFACE METHOD. I
'made it up to differentiate between CLASS and INTERFACE methods.
 
'**************************************************************
 
'Example of CLASS (just one exposed procedure)
Class MyClass
   Interface MyInterface
      Inherit IUnknown
      Method Concatenate(a$, b$) As String  : Method = (a$+b$) : End Method
   End Interface
End Class
 
'**************************************************************
 
'Example of CLASS (just one exposed variable)
Class MyClass
   INSTANCE X As Long   'variable X
   Interface MyInterface
      Inherit IUnknown
      Property Get X As Long                 : Property = X     : End Property
      Property Set X(ByVal NewValue As Long) : X = NewValue     : End Property
End Class
 
'**************************************************************
 
'Example of the parts in a CLASS:
'- INSTANCE variable,
'- CLASS METHOD
'- INTERFACE BLOCK
'- INHERIT statement
'- INTERFACE METHOD (general)
'- Special INTERFACE METHODs (CREATE and DESTROY)
'- PROPERTY GET procedure
'- PROPERTY SET procedure
 
Class MyClass
   Instance R as Long                  'INSTANCE variable
   Class Method SS() : End Method      'CLASS METHOD procedure
   Interface MyInterface               'INTERFACE block
      Inherit IUnknown                 'INHERIT statement
      Method Create()  : End Method    'INTERFACE METHOD - automatically run when object created
      Method Destroy() : End Method    'automatically run when object destroyed
      Method TT()      : End Method    'can be run by app that creates object
      Property Get R As Long        : Property = R     : End Property  'procedure allows user to get T value
      Property Get R(value As Long) : R = value        : End Property  'procedure allows user to set T value
   End Interface
End Class
 
'**************************************************************
 
'INTERFACE METHODS are exposed (available outside the object)
'There are no INSTANCE variable definitions in an INTERFACE BLOCK.
'Varaible definition occurs outside the INTERFACE BLOCK.
'PROPERTY procedures in the INTERFACE BLOCK give users access to INSTANCE variables
 
Class MyClass
   INSTANCE X AS Long
   Interface MyInterface
      Inherit IUnknown
      Method MyMethod() : [statements] :End Method
      Property Get X As Long                 : Property = X     : End Property
      Property Set X(ByVal NewValue As Long) : X = NewValue     : End Property
End Class
 
'**************************************************************
 
'HIDDEN variables and methods are placed outside the INTERFACE BLOCK.
'Such variables are called INSTANCE variables.
'To use an INSTANCE VARIABLE or CLASS METHOD inside the CLASS, start
'their name with ME, such as ME.X.
 
Class MyClass
   INSTANCE X As Long   'variable X
   Class Method MyMethod() : [statements]: End Method
End Class
 
'An INSTANCE variable is EXPOSED using PROPERTY GET/SET statements.
 
'**************************************************************
 
'This example has one INSTANCE variable and one CLASS METHOD (hidden procedure)
'It also has a pair of PROPETY GET/SET procedures to expose the INSTANCE variable
'And it has one exposed METHOD 
 
Class MyClass
   'INSTANCE variables and CLASS METHODS
   INSTANCE X As Long   'variable X
   Class Method MyMethod() : [statements]: End Method
   'exposed INSTANCES and exposed METHODS
   Interface MyInterface
      Inherit IUnknown
      Method MyMethod() : [statements] :End Method
      Property Get X As Long                 : Property = X     : End Property
      Property Set X(ByVal NewValue As Long) : X = NewValue     : End Property
End Class
 
'**************************************************************
 
'To declare a variable as an object variable, requires 2 steps.
'First, create a variable where an Interface is used instead of a data type.
   Local X As MyObjectInterface  
'Second, assign an object reference to the variable, using the CLASS name.
   Let X = MyObject
 
'Here are both steps togther:
   Local X As MyObjectInterface  
   Let X = MyObject
 
'Once the object variable is created, exposed variables and
'methods can be accessed like this:
   Local X As MyObjectInterface  
   Let X = MyObject
   ? X.value           'get on a string variable "value"
   X.value = Time$     'set on a string variable "value"
   value = X.getLastName("John") 'calls the 'getLastName procedure, puts value in string variable "value"
End Function
 
'**************************************************************
 
'PROPERTY procedures are the way an object allows access to data from
'outside the object. 
 
'Compilable Example - 1:  How to implement Property procedures
#Compile Exe
Function PBMain() As Long
   Local X As MyInterface
   Let X = Class "MyClass"
   ? X.value           'get   value is returned from Property Get procedure
   X.value = Time$     'set   Time$ is sent to Property Set procedure as NewValue
   ? X.value           'get   value is returned from Property Get procedure
End Function
 
Class MyClass
  Instance Value As String
  Interface MyInterface
    Inherit IUnknown
    Property Get Value As String                  : Property = Value : End Property
    Property Set Value (ByVal NewValue As String) : Value = "bingo" : End Property
  End Interface
End Class  
 
 
'**************************************************************
 
'You can access a PROPERTY GET with:
 
1. ObjVar.Prop1(param) TO var
2. CALL ObjVar.Prop1(param) TO var
3. var = ObjVar.Prop1(param)
 
'You can access a PROPERTY SET with:
 
1. ObjVar.Prop1(param) = expr
2. CALL ObjVar.Prop1(param) = expr
 
 
'**************************************************************
 
'Create/Destroy procedures (CLASS METHODS) are optional. If present, Create is
'automatically run first, Destory is automatically run last.  Create is generally
'used to initialize INSTANCE variables or other data
Class
   Class Method Create() : [statements]: End Method
   Class Method Destroy() : [statements]: End Method
End Class
 
'Compilable Example - 2:  Create/Destroy demonstrated - verify they execute
#Compile Exe
Function PBMain() As Long
   Local X As MyInterface        'X is object variable
   Let X = Class "MyClass"
End Function
 
Class MyClass
   Class Method Create()  : ? "created"   : End Method
   Class Method Destroy() : ? "destroyed" : End Method
   Interface MyInterface
      Inherit IUnknown
   End Interface
End Class   
 
'Compilable Example - 3:  Create/Destroy demonstrated - use to initialize INSTANCE variable
#Compile Exe
Function PBMain() As Long
   Local X As MyInterface       'X is object variable
   Let X = Class "MyClass"
End Function
 
Class MyClass
   Instance R As Long    'INSTANCE variable
   Class Method Create()  : R = 77 : ? Str$(R) : End Method  'initialize R to value of 77
   Interface MyInterface
      Inherit IUnknown
   End Interface
End Class  
 
'**************************************************************
 
'An INTERFACE METHOD can be called by the program that creates the object
'Compilable Example - 4:  Call an exposed INTERFACE METHOD
#Compile Exe
Function PBMain() As Long
   Local X As MyInterface
   Let X = Class "MyClass"
   ? X.concatenate("hi ","there")
End Function
 
Class MyClass
   Interface MyInterface
      Inherit IUnknown
      Method Concatenate(a$, b$) As String  : Method = (a$+b$) : End Method
   End Interface
End Class
 
'**************************************************************
 
'An INSTANCE variable can be retrieved/set by the program that creates the object
'Compilable Example - 5:  Get/Set only
#Compile Exe
Function PBMain() As Long
   Local X As MyInterface
   Let X = Class "MyClass"
   ? X.value           'get   value is returned from Property Get procedure
   X.value = Time$     'set   Time$ is sent to Property Set procedure as NewValue
   ? X.value           'get   value is returned from Property Get procedure
End Function
 
Class MyClass
  Instance Value As String
  Interface MyInterface
    Inherit IUnknown
    Property Get Value As String                  : Property = Value : End Property
    Property Set Value (ByVal NewValue As String) : Value = NewValue : End Property
  End Interface
End Class  
 
'**************************************************************
 
'First line of INTERFACE BLOCK must be INHERIT, which defines the
'Base Class (Interface) with which the object will be created. All
'objects have to start with a base class.
 
'The location of a called method or property can be retrieved in two ways:
'   DIRECT   - direct jump using entry point listed in VFT (virtual function table)
'   DISPATCH - object looks up method/variable name
   
'DISPATCH is slow, but was first approach. kept for compatibilty reasons.
'DIRECT is fast and is the default access method used by PowerBASIC
 
'The 3 Base Classes (Interfaces) supported by PowerBASIC are:
   IUnKnown    most basic interface definition, direct access
   IAutomation (derived from IUnKnown, direct access)
   IDispatch   (derived from IUnKnown, direct and Dispatch access)
 
'Terminology notes:
INHERIT CUSTOM     is same as INHERIT IUNKNOWN
INHERIT DUAL       is same as INHERIT IDISPATCH
INHERIT AUTOMATION is same as INHERIT IAutomation
 
'**************************************************************
 
'A CLASS may also inherit a user-written interface. If you've written
'an interface that you want to use again, you can give that interface
'to a new object with this statement:
 
   INHERIT MyClass, MyInterface
 
'This implements the base class (IUnknow/IDispatch/iAutomation) PLUS
'all of the INTERFACE METHODS and PROPERTIES of the reference INTERFACE.
 
'Compilable Example - 6:  How to implement user-defined inheritance
#Compile Exe
Function PBMain() As Long
   Local X As MyInterfaceB
   Let X = Class "MyClassB"
   ? X.value           'get   value is returned from Property Get procedure (empty until set)
   X.value = Time$     'set   Time$ is sent to Property Set procedure as NewValue
   ? X.value           'get   value is returned from Property Get procedure
   X.MyMethod          'access INTERFACE METHOD
End Function
 
Class MyClassA
   Instance value As String  'INSTANCE variable "value"
   Interface MyInterfaceA
      Inherit IUnknown       'inherits a base class
      Method MyMethod() : ? "MyMethod from MyClassA" : End Method
      Property Get value As String                 : Property = value     : End Property
      Property Set value(ByVal NewValue As String) : value = NewValue     : End Property
   End Interface
End Class
 
Class MyClassB
  Interface MyInterfaceB
    Inherit MyClassA, MyInterfaceA   'inherits a user-written interface from MyClassA above
  End Interface
End Class
 
 
'Compilable Example - 7:  How to implement user-defined inheritance
'                         but expanded to add additional Property/Method procedures
#Compile Exe
Function PBMain() As Long
   Local X As MyInterfaceB
   Let X = Class "MyClassB"
   ? X.value           'get   value is returned from Property Get procedure (empty until set)
   X.value = Time$     'set   Time$ is sent to Property Set procedure as NewValue
   ? X.value           'get   value is returned from Property Get procedure
   X.MyMethod          'access INTERFACE METHOD
   X.result = "more stuff added"  'set on new property in MyClassB
   ? X.result                     'get on new property in MyClassB
   X.MyMethodB                    'runs new method in MyClassB
End Function
 
Class MyClassA
   Instance value As String  'INSTANCE variable "value"
   Interface MyInterfaceA
      Inherit IUnknown       'inherits a base class
      Method MyMethod() : ? "MyMethod from MyClassA" : End Method
      Property Get value As String                 : Property = value     : End Property
      Property Set value(ByVal NewValue As String) : value = NewValue     : End Property
   End Interface
End Class
 
Class MyClassB
  Instance result As String  'INSTANCE variable "value"
  Interface MyInterfaceB
    Inherit MyClassA, MyInterfaceA   'inherits a user-written interface from MyClassA above
    Method MyMethodB() : ? "MyMethodB from MyClassB" : End Method
    Property Get result As String                 : Property = result     : End Property
    Property Set result(ByVal NewValue As String) : result = NewValue     : End Property
  End Interface
End Class 
 
'**************************************************************
 
'INSTANCE variable are like Global variables - they can be called
'from any procedure in the object. INSTANCE variables cannot be called
'directly from outside an object.
 
'Compilable Example - 8:  Use an INSTANCE variable within an object
#Compile Exe
Function PBMain() As Long
   Local A As MyInterface
   Let A = Class "MyClass"
   ? Str$(A.x)
End Function
 
Class MyClass
   Instance Z As Long
   Class Method SS() As Long : Z = 5 : End Method    'Z, not ME.Z
   Interface MyInterface
      Inherit IUnknown
      Property Get X As Long : ME.SS : Property = Z : End Property  'Z, not ME.Z
   End Interface
End Class
 
'**************************************************************
 
'There are 5 ways to call an INTERFACE METHOD from the application
'that created the object:
 
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.
 
'Compilable Example - 9:  Call procedures within an object
#Compile Exe
Function PBMain() As Long
   Local A As MyInterface, var As String
   Let A = Class "MyClass"
   A.tt              ' return value discarded
   Call A.tt         ' return value discarded
   A.tt To var       : ? var   
   Call A.tt to var  : ? var
   var = A.tt        : ? var
End Function
 
Class MyClass
   Interface MyInterface
      Inherit IUnknown
      Method TT() As String  : Method = Time$ : End Method
   End Interface
End Class
 
'**************************************************************
 
'To call a procedure (CLASS METHOD, INTERFACE METHOD, PROPERTY)
'from within the object itself requires the use of ME. Accessing
'INSTANCE variables does not require the use of ME.
 
 
'Compilable Example - 10:  Call procedures/variables within an object
#Compile Exe
Function PBMain() As Long
   Local A As MyInterface
   Let A = Class "MyClass"
   ? Str$(A.x)
End Function
 
Class MyClass
   Instance Z As Long
   Class Method RR() As Long : ME.SS : End Method    'ME.SS
   Class Method SS() As Long : Z = 5 : End Method    'Z, not ME.Z
 
   Interface MyInterface
      Inherit IUnknown
      Method TT()  : ME.RR : End Method             'ME.RR
      Property Get X As Long : ME.TT : Property = Z : End Property  'Z, not ME.Z
   End Interface
End Class
 
'**************************************************************
 
'A GUID is a 128-bit (16 bytes) number, usually wrtten as 32 hex characters 
'with this format: 8-4-4-4-12 digits.
 
'The PowerBASIC GUID$ function will generate a GUID:
   Local G As GUID      'GUID is now a PowerBASIC data type
   G = GUID$            'G contains a new, 128-bit GUID
 
'All CLASSES, INTERFACES, COM applications and LIBRARIES have their own, 
'unique GUID. The GUID name for each is:
 
   Class             CLSID    (friendly version is called PROGID)
   Interface         IID
   COM application   APPID
   Library           LIBID
 
'The PowerBASIC GUID$ statements generates a random GUID.
'GUID is sometimes called a UUID.
 
'GUIDs are typically ignored when you create objects
'just for internal use within your program (PowerBASIC
'randomly assigns GUIDs if you do not).
 
   Local G As GUID      'GUID is now a PowerBASIC data type
   G = GUID$            'G contains a new, unique GUID
   G = GUID$()          'parentheses are optional
   G = GUID$(guidtext$) 're-creates G from the human-readable version
   
'To be valid, the GUID string in guidtext$ string must contain exactly 
'32 hexadecimal digits, optionally delimited by spaces or hyphens, but 
'which must be enclosed overall by curly braces.  
'For example: "{01234567-89AB-CDEF-FEDC-BA9876543210}".
 
'**************************************************************
 
'COM - Common Object Model - way to communicate between code modules.
'All PowerBASIC objects are fully compatible with the COM specification
 
'COM objects are like objects internal to your program, but COM offers
'a way to use functionality on an object external to your program.
 
'Terminology: COM Component (aka COM server) can be accessed by a COM Client
'COM Component makes some INTERFACE METHODs and PROPERTY procedures public.
 
'COM Components are usually DLL/OCX or EXE. 
   'DLL/OCX is in-process
   'EXE is out-of-process
 
'When COM Component is installed, the CLSID (128-bit number) and 
'PROGID (text-friendly name) are stored in the Windows Registry.
 
'PowerBASIC COM DLL's provide self-registration and unregistration 
'services by automatically exporting two Subs:
 
Declare Function DllRegisterServer   alias "DllRegisterServer"   As Long
Declare Function DllUnregisterServer alias "DllUnregisterServerAs Long
 
'**************************************************************
 
'Clarifying Use of the Word Interface
 
'There is an INTERFACE Block within a CLASS Block. The INTERFACE Block 
'contains a list of METHOD and PROPERTY GET/SET procedures exposed by the object.
 
'There are two ways the METHOD/PROPERTY GET/SET procedures in an INTERFACE Block 
'can be accessed - a DIRECT interface and a DISPATCH interface.
 
'The word interface after DIRECT is not the same thing as the word INTERFACE in 
'front of Block. Or, put another way, the capital case I INTERFACE and the small
'case i interface are two different uses of the the word interface.
 
'INTERFACE Block is a coding construct, whereas interface is an access mechanism. 
 
'**************************************************************
 
INTERFACE
 
'**************************************************************
 
'Accessing INTERFACE methods and PROPERTY procedures is different for
'DIRECT and DISPATCH interface
 
'To call a DIRECT METHOD
   X.m(p)
   X.m(p) To var
   var = X.m(p)
 
 
To call a Method through the DISPATCH interface, you will use the OBJECT statement.  
This differentiates it from direct access, so PowerBASIC can handle your request 
in the appropriate manner.
   
'gbs_01353
'Date: 05-11-2013                           


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm