I remember coming across some way to declare multiple Set handlers in a property but now I can't figure out how it's done. It's useful in that one can assign different data types and the Set handler does the conversion, but I get the error
'Set' is already declared
thoughts anyone?
It's not possible
It would be nice to be able to write both
sQuantity = "1234"
and
sQuantity = 1234
with two setter functions, but trying to write even one setter function with the wrong parameter type seems doomed to failure:-
error BC31064: 'Set' parameter must have the same type as the containing property.
If Visual Basic doesn't allow conversion between setter parameter type and property type then there is no way it would be possible to have two setter functions. If setter functions are forced to have the same type as the property, then it could not know which to run if there were more than one!
So I'd argue 'not only does it not seem possible, but it is actually not possible!'
There is a workaround
What you can do however, is have two properties of different types changing the same underlying variable, so that you can write
sQuantityFromString = "1234"
and
sQuantityFromInt = 1234
using
Public Shared WriteOnly Property sQuantityFromInt () As Integer
with a setter function that takes an integer as a parameter and with both properties setter functions modifying the same underlying string member variable.
Private Shared m_sQuantity As String = Nothing
As far as I know, you cannot have multiple Set statements for a class property. A property cannot be overridden.
You can use a setter functions (this is mostly a paradigm in Java) and overload that if you need to. Then I would also suggest making the property readonly.
One other option is to have the property be defined as an Object and in the set check the TypeOf of the value being used to set the property and do whatever business logic you want. The only problem with this approach is that then your property doesn't have type checking.
Related
After reading this piece by Yegor about not using getters and setters, it sounds like something that makes sense to me.
Please note this question is not about whether doing it is better/worst, only if I am implementing it correctly
I was wondering in the following two examples in VBA, if I understand the concept correctly, and if I am applying it correctly.
The standard way would be:
Private userName As String
Public Property Get Name() As String
Name = userName
End Property
Public Property Let Name(rData As String)
userName = rData
End Property
It looks to me his way would be something like this:
Private userName As String
Public Function returnName() As String
returnName = userName
End Function
Public Function giveNewName(newName As String) As String
userName = newName
End Function
From what I understand from the two examples above is that if I wanted to change the format of userName (lets say return it in all-caps), then I can do this with the second method without changing the name of the method that gives the name through - I can just let returnName point to a userNameCaps property. The rest of my code in my program can still stay the same and point to the method userName.
But if I want to do this with the first example, I can make a new property, but then have to change my code everywhere in the program as well to point to the new property... is that correct?
In other words, in the first example the API gets info from a property, and in the second example the API gets info from a method.
Your 2nd snippet is neither idiomatic nor equivalent. That article you link to, is about Java, a language which has no concept whatsoever of object properties - getFoo/setFoo is a mere convention in Java.
In VBA this:
Private userName As String
Public Property Get Name() As String
Name = userName
End Property
Public Property Let Name(rData As String)
userName = rData
End Property
Is ultimately equivalent to this:
Public UserName As String
Not convinced? Add such a public field to a class module, say, Class1. Then add a new class module and add this:
Implements Class1
The compiler will force you to implement a Property Get and a Property Let member, so that the Class1 interface contract can be fulfilled.
So why bother with properties then? Properties are a tool, to help with encapsulation.
Option Explicit
Private Type TSomething
Foo As Long
End Type
Private this As TSomething
Public Property Get Foo() As Long
Foo = this.Foo
End Property
Public Property Let Foo(ByVal value As Long)
If value <= 0 Then Err.Raise 5
this.Foo = value
End Property
Now if you try to assign Foo with a negative value, you'll get a runtime error: the property is encapsulating an internal state that only the class knows and is able to mutate: calling code doesn't see or know about the encapsulated value - all it knows is that Foo is a read/write property. The validation logic in the "setter" ensures the object is in a consistent state at all times.
If you want to break down a property into methods, then you need a Function for the getter, and assignment would be a Sub not a Function. In fact, Rubberduck would tell you that there's a problem with the return value of giveNewName being never assigned: that's a much worse code smell than "OMG you're using properties!".
Functions return a value. Subs/methods do something - in the case of an object/class, that something might imply mutating internal state.
But by avoiding Property Let just because some Java guy said getters & setters are evil, you're just making your VBA API more cluttered than it needs to be - because VBA understands properties, and Java does not. C# and VB.NET do however, so if anything the principles of these languages would be much more readily applicable to VBA than Java's, at least with regards to properties. See Property vs Method.
FWIW public member names in VB would be PascalCase by convention. camelCase public member names are a Java thing. Notice how everything in the standard libraries starts with a Capital first letter?
It seems to me that you've just given the property accessors new names. They are functionally identical.
I think the idea of not using getters/setters implies that you don't try to externally modify an object's state - because if you do, the object is not much more than a user-defined type, a simple collection of data. Objects/Classes should be defined by their behavior. The data they contain should only be there to enable/support that behavior.
That means you don't tell the object how it has to be or what data you want it to hold. You tell it what you want it to do or what is happening to it. The object itself then decides how to modify its state.
To me it seems your example class is a little too simple to work as an example. It's not clear what the intended purpose is: Currently you'd probably better off just using a variable UserName instead.
Have a look at this answer to a related question - I think it provides a good example.
Regarding your edit:
From what I understand from the two examples above is that if I wanted
to change the format of userName (lets say return it in all-caps),
then I can do this with the second method without changing the name of
the method that gives the name through - I can just let returnName
point to a userNameCaps property. The rest of my code in my program
can still stay the same and point to the method iserName.
But if I want to do this with the first example, I can make a new
property, but then have to change my code everywhere in the program as
well to point to the new property... is that correct?
Actually, what you're describing here, is possible in both approaches. You can have a property
Public Property Get Name() As String
' possibly more code here...
Name = UCase(UserName)
End Property
or an equivalent function
Public Function Name() As String
' possibly more code here...
Name = UCase(UserName)
End Function
As long as you only change the property/function body, no external code needs to be adapted. Keep the property's/function's signature (the first line, including the Public statement, its name, its type and the order and type of its parameters) unchanged and you should not need to change anything outside the class to accommodate.
The Java article is making some sort of philosophic design stance that is not limited to Java: The general advise is to severely limit any details on how a class is implemented to avoid making one's code harder to maintain. Putting such advice into VBA terms isn't irrelevant.
Microsoft popularized the idea of a Property that is in fact a method (or two) which masquerade as a field (i.e. any garden-variety variable). It is a neat-and-tidy way to package up a getter and setter together. Beyond that, really, behind the scenes it's still just a set of functions or subroutines that perform as accessors for your class.
Understand that VBA does not do classes, but it does do interfaces. That's what a "Class Module" is: An interface to an (anonymous) class. When you say Dim o As New MyClassModule, VBA calls some factory function which returns an instance of the class that goes with MyClassModule. From that point, o references the interface (which in turn is wired into the instance). As #Mathieu Guindon has demonstrated, Public UserName As String inside a class module really becomes a Property behind the scenes anyway. Why? Because a Class Module is an interface, and an interface is a set of (pointers to) functions and subroutines.
As for the philosophic design stance, the really big idea here is not to make too many promises. If UserName is a String, it must always remain a String. Furthermore, it must always be available - you cannot remove it from future versions of your class! UserName might not be the best example here (afterall, why wouldn't a String cover all needs? for what reason might UserName become superfluous?). But it does happen that what seemed like a good idea at the time the class was being made turns into a big goof. Imagine a Public TwiddlePuff As Integer (or instead getTwiddlePuff() As Integer and setTwiddlePuff(value As Integer)) only to find out (much later on!) that Integer isn't sufficient anymore, maybe it should have been Long. Or maybe a Double. If you try to change TwiddlePuff now, anything compiled back when it was Integer will likely break. So maybe people making new code will be fine, and maybe it's mostly the folks who still need to use some of the old code who are now stuck with a problem.
And what if TwiddlePuff turned out to be a really big design mistake, that it should not have been there in the first place? Well, removing it brings its own set of headaches. If TwiddlePuff was used at all elsewhere, that means some folks may have a big refactoring job on their hands. And that might not be the worst of it - if your code compiles to native binaries especially, that makes for a really big mess, since an interface is about a set of function pointers layed out and ordered in a very specific way.
Too reiterate, do not make too many promises. Think through on what you will share with others. Properties-getters-setters-accessors are okay, but must be used thoughtfully and sparingly. All of that above is important if what you are making is code that you are going to share with others, and others will take it and use it as part of a larger system of code, and it may be that these others intend to share their larger systems of code with yet even more people who will use that in their even larger systems of code.
That right there is probably why hiding implementation details to the greatest extent possible is regarded as fundamental to object oriented programming.
I'm trying to understand something about type properties in swift.
The Swift Programming Language says
For classes, you can define computed type properties only
So a computed property does not store a value itself, but it is calculated. That I understand. But I don't get how such a thing can apply to type properties. Such properties belong to the class itself and not to an instance of it.
So if you use a getter for such a computed type property, what could you possibly use to calculate it? It can't be any other type properties, as they too can only be computed properties. You would get a sort of loop of computed properties because there aren't any stored type properties.
In the same way, I also don't get what a setter would do. If you call the setter of a computed type property, what can it set? There are no stored type properties to be set.
Bear in mind that stored class properties are only unsupported at the moment. The compiler error you get when you try to use them—"Class variables not yet supported"— suggests that they're on their way. Computed class properties don't necessarily have to make sense on their own.
However, computed properties don't always have to be based on the values of stored data. As it stands, you could use them for "static" read-only values associated with the class, say:
class var ThisIsAClassConstant: String { return "Woo" }
And people have already come up with ways to store associated values, for example, in the first two singleton patterns in this answer, the class property stores its state in either a global (but private) variable, or in a static variable inside a nested structure.
These are obviously a bit "workaroundy", but they're a way of achieving class-like storage while it's not officially implemented.
I have a class call CalcArray that has an array of doubles called Amounts(), and two ints, StartPeriod and EndPeriod.
The user almost always wants to interact with the items in the array, not the Periods or the object itself. So ideally, I'd like:
property AnAmount() as CalcArray 'So the user can talk to the object if they need to
property AnAmount(i as Integer) as Double 'So the user can just get the value directly
This seems to work sometimes and not others. Is this simply a syntax issue? or is such an overload not possible?
You can do this with a function returning a different based on how it is called. Especially since you have a param, a function might be more appropriate:
Public Function AnAmount(Of T)(parm As SomeType) As T
to use it:
Dim n as Decimal
n = AnAmount(Of Decimal)(foo)
Its very useful as a way to avoid returning an object and then have to use CType to convert the return. In this case, an amount implies a value type, but the function would accept Point, Rectangle etc as T, so you might need to check valid type requests.
You may be bumping into the limitation that a function or property cannot vary by only the return type. In general if the signature has changed, the output type can change also on an overload. Look out also for the limitation for using default properties requires an argument. In some cases class inheritance is the issue, properties and functions being shadowed may explicitly be required to nominate Shadows, Overloads, Overrides etc. or the shadowing will be disallowed by the language.
If these don't cover the cases you've seen, try to catch an example of the problem and study all locations of the same named property in your solution, reporting the results here.
Let's assume I have a class and whenever I set certain attributes bla, foo (which can be set externally and internally) I want to call another method of the class, let's call it onChangeFunction().
Would it be a good way to simply call onChangeFunction() when setting internal values directly, e.g.
function someFunction()
// Some Calculations here ...
this.bla = some_value;
this.onChangeFunction()
end
or would it be better to also set those variables bla and foo ONLY by using the internal setter-methods because there is a certain action triggered with it and thus it would be a more clearly arranged code.
I even go a step further: Let's say I don't need an extern setter which can be called from outside (access type = public), would it than still be good to invent a private setter to do the same approach and only use the setter because of the triggered set-action?
EDIT: What I mean is the following: Even if I would NOT have a public setter (because there should not be a public access to set the variable, because it's only an internal variable) would it be still good to have a setter which is private-only just because of the triggered action thing?
Thanks in advance!
I think in the long term it is much less error-prone to always use a setter, and to call onChangeFunction() from within the setter.
You don't specify which programming languages you have in mind, but some languages allow one to define a "property" that looks like a data member but always calls a function when an attempt is made to change it. See, for example, property et al in Python.
As to your second question, I don't think there's anything wrong with having a private setter.
Is setX() method name appropriate for only for setting class property X?
For instance, I have a class where the output is a string of an html table. Before you can you can call getTable, you have to call setTable(), which just looks at a other properties and decides how to construct the table. It doesn't actually directly set any class property -- only causes the property to be set. When it's called, the class will construct strHtmlTable, but you can't specify it.
So, calling it setTable breaks the convention of get and set being interfaces for class properties.
Is there another naming convention for this kind of method?
Edit: in this particular class, there are at least two ( and in total 8 optional ) other methods that must be called before the class knows everything it needs to to construct the table. I chose to have the data set as separate methods rather than clutter up the __construct() with 8 optional parameters which I'll never remember the order of.
I would recommend something like generateTable() instead of setTable(). This provides a situation where the name of the method clearly denotes what it does.
I would probably still use a setTable() method to actually set the property, though. Ideally, you could open the possibility of setting a previously defined table for further flexibility.
Yes, setX() is primarily used for setting a field X, though setX() may have some additional code that needs to run in addition to a direct assignment to a field. Using it for something else may be misleading to other developers.
I would definitely recommend against having a public setTable() and would say that setTable() could be omitted or just an unused private method depending upon your requirements.
It sounds like the activity to generate the table is more of a view of other properties on the object, so you might consider moving that to a private method on the object like generateHtmlTable(). This could be done during construction (and upon updates to the object) so that any subsequent calls to getTable() will return the the appropriate HTML.