Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Class Attributes vs Method Parameters (Arguments) 3

Status
Not open for further replies.

1DMF

Programmer
Jan 18, 2005
8,795
GB
Hi,

While refactoring a class, it occured to me that one method would actually benefit from taking arguments rather than using attributes which would need to be set via accessor methods before the protocol method could be called.

How do you decide when to use attributes for public class method fucntionality vs methods which accept parameters?

Is there a rule that says protocol (public) methods should always work with attributes and not take arguments?

Is it simply a case of what is easiest to work with for a particular action?

Now perhaps in a true OO languages; as you have a contructor (which you don't in Access), you can overload them with various parametised signatures, which would set attrbutes as the object is instantiated, but as there is no contructor that takes arguments nor can it be overloaded in Access, it makes initialising attributes via a contructor impossible.

Though correct me if I'm wrong, but as understand things all you get in Access is "Private Sub Class_Initialize()" which takes no arguments and cannot be overloaded?

All input is appreciated.

Regards,
1DMF.

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Free Dance Music Downloads
 
Is there a rule that says protocol (public) methods should always work with attributes and not take arguments?

Not that I know of. I suppose that in a perfect OO world that's a preferred practice but, as you said, VB is not that world. VB doesn't do anything that you could mistake for overloading.

I have used Class_Initialize to do things like pull data from a database to initialize attributes but that's sort of cheating since the database initialization occurs outside the class which is of course a violation of all sorts of OO principles. Come to think of it though ... I suppose I could build another class to do the data base initialization stuff ... Hmmmm ...

Your class code in the other thread for example, does set attributes that are then used in a public method and you have the somewhat annoying necessity of validating those attributes before you can proceed. As you pointed out, in a true OO language there are ways of dealing with that but, sadly, not in VB.

 
Hi Golom,

Thanks for the input, and it was that exact method I was refactoring as it seemed anal to have to set the attributes via accessor methods before calling the public method.

I've changed it to the folowing
Code:
Public Function Missing(Optional ByVal sCat As String, Optional ByVal sStat, Optional ByVal sType As String, Optional ByVal sDoc As String) As String
       
    If Not IsMissing(sCat) Then
        sCategory = sCat
    End If
    
    If Not IsMissing(sStat) Then
        sStatus = sStat
    End If
    
    If Not IsMissing(sType) Then
        sRecType = sType
    End If
    
    If Not IsMissing(sDoc) Then
        sDocs = sDoc
    End If
       
    If IsNull(sCategory) Or IsNull(sStatus) Or IsNull(sRecType) Or IsNull(sDocs) Then
        MsgBox "You must set Category,Status,RecType & Docs before running this method"
        Missing = ""
        Exit Function
    End If
    
    Dim oDoc As Variant
    
    For Each oDoc In getDocs()
        If Nz(InStr(1, sDocs, oDoc, vbTextCompare), 0) = 0 Then
            If Missing <> "" Then
                Missing = Missing & ","
            End If
            Missing = Missing & oDoc
        End If
    Next
    
End Function

This way it can be used either way, by either passing in optional arguments or use accessor methods to set the attributes, which is a compromise and allows for a simple change to a single attribute before calling the method again.

I assume this would be considered perfectly accceptable in a VBA world?

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Free Dance Music Downloads
 
>as you have a contructor (which you don't in Access),

However you can use a factory class (for example see my code in this example from about 10 years ago: thread222-306193)
 
Ah, gotya, thanks Mike.

So you have a class with methods for contructing other objects.

So the factory methods take arguments, instantiates the desired object, sets the object attributes and passes back the object!

Though that means there is a method (constuctor) outside of the actual class itself doesn't it?

It also means you have to instiate two object to create one.

Does this mean in your oppinion it's wrong to have class methods in the 'real' object class that accepts arguments?

Also would you see an issue if you made the 'factory class' a standard module so there is no requirement to instantiate two objects?

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Free Dance Music Downloads
 
>Does this mean in your oppinion it's wrong to have class methods in the 'real' object class that accepts arguments?

No. I'm more than happy to create class methods that take arguments

Note that class factories are a pretty well established paradigm of OOP, and can do a lot more than provide you with the constructors that VB is missing ( And I don't really see anything wrong with instantiating two objects since it doesn't hurt
 
Having played around with implementing a Factory class, it seems it doesn't actually solve the problem, unless I'm missing something or doing it wrong.

It seems you still need to make public accessor methods (properties) for the private attributes?

The point of having a parameterised constructor and part of OOP principles is data hiding / encapsulation.

It doesn't seem posible to follow this paradigm using a Factory class in VBA?

The goal is to have all attributes private without any accessor methods and use a parameterised contructor to initialise the attributes upon instantiation of the object.

Am I correct in thinking this OOP priciple is not possible using VBA?




"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Free Dance Music Downloads
 
Yes these are all limitations of VBA which are a lot. The world would be great if you could use vb.net instead. So in order to make it work more OOP like you have to come up with unique work-arounds. So since everything is a work-around I think the only rules that applies are "does it work and make sense". My work around is that I have a fake constructor in my classes called MyInitialize. I do this consistently in my classes so that is my work-around paradigm. So when I instantiate it looks like

dim ccSomeClass as CustomClass
set ccSomeClass = new CustomClass 'Unfortunately vba does not allow parameters and the real initialize fires here
ccSomeClass.myInitialize "someValue", parameter, 2 .... 'My fake constructor

In the class, myInitialize is simply a procedure that takes parameters and sets a boolean property to true

so in the class

private mIsInitialized as boolean

Public sub myInitialize(...arguments....)
code
mIsInitialized = true
end sub

public property Get Initialed() as boolean
Initialized = mIsInitialized
end property


so then when I try to use the object, I can first ensure that it has been fake initialized (my fake constructor has been used)
if ccSomeClass.initialized then....

My fake constructor may have some optional parameters thus faking overloading.
 
Cool Thanks, MajP.

It's nice to know I did learn something on my OOP course, and that I am understanding the limitations and inability to apply some of the principles I was taught.

I'm happy with my public method taking parameters that set the attributes, as it is a working work-around, I just wanted to be sure I was understanding things correctly and the limitations of the environment I am working with.

It's always good to have someone re-affirm your conclusions.

kind regards,

1DMF.

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Free Dance Music Downloads
 
No, you are not correct.

But VBA does require a little bit of work to do it.

The main challenge is that all properties, methods etc within a VBA class module are visible throughout that project, no matter what the setting (e.g. Private, Public) - Private only really makes them private from another project (and in VBA does not always do that for class-scoped variables)

So the first step is that your class library project needs to be saved, then added as a reference to your consumer project

Secondly, you'll want to look at the Friend keyword

Ok, an example using Excel

The first workbook, we have a VBA project (rename it, BTW, say xlSizerProject) which requires a module and two classes, each class set to PublicNotCreatable

First class, let's say called xlSizer

Code:
[blue]Option Explicit

Friend Property Let setsize(lSize As Long) ' will not be visible outside this project
    size = lSize
End Property

Public Property Get Multisize() As Long
    Multisize = size * 4
End Property[/blue]

Second class, let's say called xlSizerFactory

Code:
[blue]Option Explicit

Public Function MakeSizer(lSize As Long) As xlSizer
    Set MakeSizer = New xlSizer
    MakeSizer.setsize = lSize
End Function[/blue]

And in the module:

Code:
[blue]Option Explicit

Public size As Long

Public Function GetFactory() As xlSizerFactory
    Set GetFactory = New xlSizerFactory
End Function[/blue]

OK save the workbook, let's say as xlSizer.xlsm (assuming Excel 2007/2010) and exit it. Create a new blank workbook. In the VBA project add a reference to xlSizer.xlm just as you would any class library DLL (you'll have to browse to wherever you saved it). Now add the following code:

Code:
[blue]Option Explicit

Public Sub example()
    Dim myFactory As xlSizerFactory
    Dim mySizer As xlsizer
    
    Set myFactory = xlSizerProject.GetFactory
    Set mySizer = myFactory.MakeSizer(6)
    
    Debug.Print mySizer.Multisize
    
    Stop ' you can examine locals' properties now we've stopped.
End Sub[/blue]
 
Sorry you've lost me Mike, I don't do VBA for anything other than Access and I certainly don't reference DLL's or anything else the way you seem to indicate? The classes and modules are all part of the project (Access 'ACCDB'), but from what I can see you still have public properties in the concrete class you are tying to instantiate (xlSizer) and it doesn't have any attributes, there seems to be a global project public variable 'size' which the class accesses, which doesn't make any sense to me in the context of my question?

I've tried accessing attributes from a class that doesn't make them accessible via public properties and the code won't compile.

I thought you can only access privately declared class attributes from either within the class they are delcared or via accessor methods (properties)? This I was taught in my OOP course is a fundamental principle of OOP known as data hiding & encapsulation?

You are not even meant to access superclass attributes from a subclass according to my OU OOP Java course, though another OU course I took did allow direct access to superclass attributes, but we were taught technically this is not correct OOP even though some environments allow super.attribute or ClassName.attribute, but it was more a bug / quirk of the IDE environment the course provided.

The same as using suitability / substitution and declaring an obejct as a superclass allows you to pass it a variable declared as a subclass but will not allow access to the subclass protocol without casting it to the correct data type, though again a bug in the IDE didn't follow this apparent OOP principle.

Have I been taught incorrectly?






"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Free Dance Music Downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top