Date: 02-16-2022
Return to Index
created by gbSnippets
'**************************************************************
'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 "DllUnregisterServer" As 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
http://www.garybeene.com/sw/gbsnippets.htm