Here is a VB.NET code snippet
Public Class OOPDemo
Private _strtString as String
Public Function Func(obj as OOPDemo) as boolean
obj._strString = "I can set value to private member using a object"
End Function
End Class
I thought we cannot access the private members using the object, but perhaps CLR allows us to do that. So that means that access modifiers are based on the type and not on the instance of that type. I have also heard that c++ also allows that..
Any guesses what could be the reason for this?
Edit:
I think this line from the msdn link given by RoBorg explains this behaviour
"Code in the type that declares a private element, including code within contained types, can access the element "
Your question is quite confusing but I think I've understood it as:
"Why can I access another instance (of my class)'s private variables?"
And you're right - in all OOP languages I've used you can access private variables from other instances, precisely because access permissions are based on where the code is, rather than to which object instance it 'belongs'.
It might be hard to implement copy constructors or equality operators otherwise.
Here's the section about access levels in MSDN.
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 having trouble inheriting a (public) variable, let's say
Public Var As ClassThatIsIndependent
The declaration above generates no trouble for itself, however, if i inherit the class that holds it
Implements BaseClass
I get the error "object module needs to implement variable for interface". I've tried these options (both inside ChildClass)
Public Var As ClassThatIsIndependent
and
Public BaseClass_Var As ClassThatIsIndependent
But none of them solves the problem. Any alternative? I'm open to possible Set/Get solutions, however, i'd prefer to maintain Var as a public variable.
Per the Visual Basic 6.0 Programmer's Guide, Polymorphism, Implementing Properties section:
Suppose we give the Animal class an Age property, by adding a Public variable to the Declarations section:
Option Explicit
Public Age As Double
The Procedure drop downs in the code modules for the Tyrannosaur and Flea classes now contain property procedures for implementing the Age property,
…
Using a public variable to implement a property is strictly a convenience for the programmer. Behind the scenes, Visual Basic implements the property as a pair of property procedures.
You must implement both procedures. The property procedures are easily implemented by storing the value in a private data member, as shown here:
Private mdblAge As Double
Private Property Get Animal_Age() As Double
Animal_Age = mdblAge
End Property
Private Property Let Animal_Age(ByVal RHS As Double)
mdblAge = RHS
End Property
The private data member is an implementation detail, so you have to add it yourself.
That is, the "public interface" is exactly the same whether you use a Public variable or define them with Property Get/Let. And to implement a property in an interface, you can't use the Public variable approach and need to use the Property Get/Let syntax and handle the data storage for it in your own private variables.
Ok, so this kind of follows after a previous question that I've asked involving structures and classes. So referencing this question (and I am using classes now for the base) I have one member of the class that is an array (and I know that I have to declare it without dimensions) that as part of the constructor I want it to define the dimensions of the array. When I was initially trying to do the ReDim the compiler was unhappy because I was declaring the member as ReadOnly. While what I'm doing with the array has it's own question of feasibility to it that's not what I'm asking about as it raised a different issue that I must answer first.
Is there a way to make members of a class/structure read only outside of the class/structure but modifiable with in the class/structure without having to use properties or internal functions/subs to gain the read access?
Basically like declaring the member private but you can at least read the member outside the class/structure. Just not anything else.
You can do something like this
Private _some As String
Public Property Some As String
Get
Return _some
End Get
Private Set(value As String)
_some = value
End Set
End Property
No. On its own, there is no way to make a class field public for reading, but private for writing. Accessibility modifiers on a field affect both read and write.
The cleanest way to do what you want is to define a private field in your class, and define a public property getter:
Private _dummy As String
Public Property Dummy() As String
Get
Return _dummy
End Get
End Property
Granted, it would be nice to be able to express this more succinctly, as is possible with C# using auto-implemented properties:
public string Dummy {get; private set;}
This question already has answers here:
Are static local variables bad practice?
(2 answers)
Closed 8 years ago.
Consider the following functionally two code snippets in a single-threaded environment. Assuming there are no other methods in Foo I believe these are functionally identical.
Class Foo
Private _Bar As Bar
Public ReadOnly Property GetBar As Bar
Get
If IsNothing(_Bar) Then
_Bar = New Bar
End If
Return _Bar
End Get
End Property
End Class
And
Class Foo
Public ReadOnly Property GetBar2 As Bar
Get
Static _Bar As New Bar
Return _Bar
End Get
End Property
End Class
Today I was challenged on code following the 2nd method because "the New will be called each time". I already know that is false, but the primary objection was with regards to the use of Static. I found several references to Static variables indicating that they may be dangerous, but they were all talking about Java. However, I was not able to find any good explanations as to why.
How are these two methods different? Is the 2nd method dangerous? If so, why?
Static in VB.Net is not that same as static in Java, C#, C, or C++. VB.Net's analog to that construct is Shared. The documentation on the Static keyword is here:
http://msdn.microsoft.com/en-us/library/z2cty7t8.aspx
In particular, I'd like to point out this snippet:
Behavior
When you declare a static variable in a Shared procedure, only one copy of the static variable is available for the whole application. You call a Shared procedure by using the class name, not a variable that points to an instance of the class.
When you declare a static variable in a procedure that isn't Shared, only one copy of the variable is available for each instance of the class. You call a non-shared procedure by using a variable that points to a specific instance of the class.
It's likely the objection comes from believing that Static always behaves like the first paragraph, even in instance methods, when we can see here that it's clearly documented that this is not the case.
Instead, Static allows you to declare a variable whose lifetime-scope is that of the class instance, but whose access-scope is limited to a single method. It's a way to narrow the potential scope of a variable, and therefore is a good thing. Additionally, variables declared as Static are rewritten by the compiler to be protected via the Monitor class (at least for the Shared version), giving them a measure of thread-safety. In other words, a variable declared as Static is more likely to have any needed locking done verses a similar class-scoped variable.
In this particular case, though, I fail to see the point. You don't really gain anything beyond an auto-implemented property like this:
Public ReadOnly Property GetBar2 As New Bar()
This probably is confusing the VB.net concepts of Static and Shared because some languages use the keyword Static to mean what VB uses Shared for: a variable/field/property/method that is shared or common to all instances of a class.
But Static doesn't mean that in VB. Instead it means a routine-local variable that persists beyond the invocation of the routine (i.e., its lifetime is object-scoped rather than routine invocation-scoped).
REF: http://msdn.microsoft.com/en-us/library/z2cty7t8.aspx
So in VB, Static means "routine-scoped visibility, object-scoped lifetime".
Whereas Shared means "class-scoped visibilty, class/program-scoped lifetime".
I would avoid the second approach if for no other reason than the fact that C and C# have a static keyword whose meaning is totally different from that of the VB.NET Static keyword. I generally dislike language features which look like features of other languages but aren't. If it's necessary to use a language feature despite its unfortunate resemblance to the other language's feature, I'll use it, but the VB.NET static keyword doesn't really add much here. Effectively, it asks the compiler to make the variable Private field, give it an arbitrary name which differs from that of any other field, and replace all references to the variable's given name within the method with references to the invented name.
Conceptually, use of such "localized" fields may be regarded as dubious because while one may expect that a field will only need to be used within one method, that may turn out not to be true. I wouldn't worry too much about that issue in vb.net, however, because a Static variable may easily be turned into an ordinary private field if the need arises. If when that need does arise a field exists with the same name, one may easily rename the Static variable before moving it.
Can anyone explain me in VB i need to use Public Shared Sub so it can be accessed from another form.
But what this "Public" and "Shared" means?
Who is public?
With who is shared?
If it is public shared does this means some other software or "some hacker app" can easier have access to this sub and it's values?
In VB.NET, Shared is equivalent to static in C# - meaning the member belongs to the class, not an instance of it. You might think that this member is 'Shared' among all instances, but this is not technically correct, even though VB.NET will resolve a Shared member though an instance invocation.
public class1
public shared something as string
public somethingelse as string
end class
The following code illustrates how VB.Net allows you to access these:
...
class1.something = "something" 'belongs to the class, no instance needed
dim x as new class1() with {.somethingelse = "something else"}
Console.WriteLine(x.somethingelse) 'prints "something else"
Console.Writeline(class1.something) 'prints "something" <- this is the correct way to access it
Console.Writeline(x.something) 'prints "something" but this is not recommended!
...
Public means any linking assembly can see and use this member.
The Public accessor keyword simply means that the method, property, etc. is visible and callable from outside of the DLL or Assembly that defined it.
The Shared keyword means that the method, etc. is not "instanced". That is, it is part of the Class definition only, and not part of the objects that are created ("instanced") from that Class definition. This has two principal effects:
The Shared method can be called at anytime, without actually having an object/instance of that Class. and,
Shared methods cannot access any of the non-Shared parts of the Class definition (unless an object instance is passed to it). They can only directly access the other Shared parts of the Class definition.