I have a question regarding "Public Property" to access a private variable. If I am following the book right and I usually do I have this syntax correct. I mean literally copied right out of Tony Gaddis's bible here but MSVS is throwing me an an error. This is the code I have, its literally just the beginning declarations for a small bank account assignment.
Code:
Public Class AccountClass
Private intBalance As Integer
Private intRate As Integer
Private intIntrest As Integer
Private intTransactions As Integer
Public Property intBalance() As Integer
Get
Return intBalance
End Get
Set(ByVal value As Integer)
End Set
End Property
The error I get says "intBalance is already declared as private "intBlance" as integer in this class.
I have no other idea how to get this to fly since I'm doing the same thing that is in the book. Anyone throw me a hand?
Abrium Asking the beginners questions so you don't have to! If by chance hell actually froze over and I some how helped you... Please rate.
You can't give the field and the property the same name. There are various conventions used to visually associate a property with its backing field. The one I use would mean your declarations would be:
vb.net Code:
Private _balance As Integer
Public Property Balance() As Integer
Another convention would be to use "Balance" for the property and "balanceValue" for the field.
Seriously, get rid of the Hungarian notation. Do you forget that the Text property of a control is a String because it's not "strText"?
I'm not sure what you mean by "stay alive". The whole point of properties is that from the outside they behave like fields while allowing you to do things on the inside that you can only do in methods, e.g. perform validation or raise events. As such, you use the property in code in exactly the same way as you would if there was no property and you were accessing the field directly.
I'm not sure what you mean by "stay alive". The whole point of properties is that from the outside they behave like fields while allowing you to do things on the inside that you can only do in methods, e.g. perform validation or raise events. As such, you use the property in code in exactly the same way as you would if there was no property and you were accessing the field directly.
If that is the case, considering them a field, how do you populate them from user input or use them. Sorry these are all new to me and this book is quickly becoming a door stop.
Abrium Asking the beginners questions so you don't have to! If by chance hell actually froze over and I some how helped you... Please rate.
Do you know how to set a variable? If so then you know how to set a property. As I have already said, part of the point of properties is that they behave exactly like fields, i.e. member variables, from the outside.
I am betting that by "stay alive" the op means "Stay in scope" or "hold its value" in reference to the field declared at the Class level.
@Abruim:
It took me a while to understand the point of Public Properties and Private Fields (and at some times, I can still irritate folks on here by using them wrong!). However, think of it like this:
A. The Private Field is hidden to the "outside" world, and is manipulated only by code WITHIN the class itself. Your own code can do stuff to it, unbeknownst to an outside "Actor" which can be (and usually is) a method on some OTHER class.
B. THe Public Property is "Exposed" to the outside (again, generally meaning code located on other classes), and is where such code is able to set the value of the Private field. This gives YOU, the programmer, control over HOW the value will be set ("Validation"), and in some cases, WHAT happens when the value is set/Changed, etc.
Now, for example, Drag a control (say, a textbox) onto a form in vs. When you access the Textbox programmatically, and Intellisense "helps you" by providing a list of properties and methods, those properties and methods exposed by Intellisense are the PUBLIC ones. Note the TextBox.Text Property. Invisibly, behind the scenes, there is a Backing field within the textbox class, PROBABLY named _Text, which holds a String value as set by the user (in this case, YOU) through the PUBLIC Property.
Notice that from the "outside" as it were, you cannot see, hear, touch, smell, or otherwise interact with this private fieild. However, when code WITHIN the textbox class needs to perform some operation on the String which you see displayed in the Textbox on the form, it is the private field which is (usually) being manipulated.
From a programming perspective, you the programmer get access, within your code, only to the public property TextBox.Text.
If you want to explore this more thouroughly, check out the .NET Reflector (google it). With this handy tool, you CAN see "Inside" the code for much of the .NET framework. I haven't looked at the Textbox this way myself, but I am betting you will find a Public Property declaration for "Text", and somewhere farther down, a private field named _text. The public Property will look very much like your own, except that it will have both the GET and the SET methods (you really should either preform the Set as well as the Get, or declare the property "ReadOnly" . . .\
Oh, and by the way, the private field will "stay alive" (stay in Scope) as long as the class which contains it, or until your code performs some actions which "kills it" (changes the value or sets it to "Nothing").
Or of course, the calling code/or user chages it, through the public property . . .
If I muffed any of that, jmc will straighten it out right quick, and without mercy!
If you want a varaible to maintain scoipe for the life of the application, you will need to declare it in a MODULE. In certain specialized cases, you might examine using the Project.Settings to hold certain values, but that is probably NOT what you are looking for in this case.
This is all great GREAT information guys, thanks. I am starting to get the hang of this. For example this is what I have right now:
Code:
Public Property Balance() As Integer
Get
Return intBalance
End Get
Set(ByVal value As Integer)
intBalance = value
PopulateForm()
End Set
End Property
IntBalance is privately declared in the class. I am using the public property to set the value of that variable. HOWEVER, Now for some odd reason I can't get that damn value to populate in a textbox on another form. I know it has to do with the accessibility of that variable. I can MB in my PopulateForm function and see that intBalance holds the correct value BUT I can't figure out how to get that value to populate into a text box on another form. I even tried using the public property variable Balance. This is what I have in PopulateForm:
Code:
Sub PopulateForm()
MessageBox.Show(Balance)
FrmMain.txtAccntBalance.Text = NewAccount.Balance
FrmMain.lblTest.Text = Balance
FrmMain.txtIntRate.Text = intRate
FrmMain.txtTotalBalance.Text = intWithIntrest
FrmMain.txtNumTransactions.Text = intTransactions
End Sub
Like I said, I know the variable is holding the value but it is NOT populating in the txtbox on FrmMain. Any suggestions there?
I do apologize I am working through this literally 1 line at a time to try and figure this out.
Abrium Asking the beginners questions so you don't have to! If by chance hell actually froze over and I some how helped you... Please rate.
You should not be calling that PopulateForm method inside the property setter. The AccountClass shouldn't even have to know about the form. It should be the other way around: the form should know about the Account. If you want the form to be updated when the property is updated then you should have an event to provide notification, much like the TextChanged event of a TextBox. Your form can then handle that event and update its own TextBox whenever the Balance property of the Account changes. You could also bind the TextBox to the Account object and the event handling and updating would occur automatically in both directions.
I put the popform method inside that property just to see if the data would populate in the form. Purely testing here, and its not. Still working on it.
Abrium Asking the beginners questions so you don't have to! If by chance hell actually froze over and I some how helped you... Please rate.
Ok I have been at this for an hour with no avail... I give up. Let me lay this down for you and see if I can get some answers because I'm tired of pulling my hair out. I have the following:
Two Form Classes:
FrmMain and FrmDeposit
I have my own created class:
AccountClass
Here is my minimal ****in code for these guys.
FrmMain
Code:
Option Strict On
Imports System.IO
Public Class FrmMain
Public NewAccount As New AccountClass
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
FrmDeposit.ShowDialog()
End Sub
End Class
FrmDeposit:
Code:
Public Class FrmDeposit
Private Sub btnThankYou_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnThankYou.Click
Dim IncomingDeposit As Integer
IncomingDeposit = txtDepositAmount.Text
FrmMain.NewAccount.Balance = IncomingDeposit
Me.Close()
End Sub
End Class
And finally my own Class
Code:
Option Strict On
Imports System.IO
Public Class AccountClass
'Member variables of class
Private intBalance As Integer
'Private intRate As Integer
'Private intWithIntrest As Integer
'Private intTransactions As Integer
Public Property Balance() As Integer
Get
Return intBalance
End Get
Set(ByVal value As Integer)
intBalance = value
End Set
End Property
End Class
I have frmmain show up, hit the "deposit button" enter a value in the frmdeposit that pops up. I just can't get the data to flow around I've looked over the programming examples in my book and nothing is mentioned or talked about passing private information across forms. I lost some functionality but rest assured it isn't correct. I'm going to get up and get a beer. Anyone wanna help me out with a crash course in this, I'm getting extremely frustrated. I know, I know JM and Runs that the answer is painfully obvious to yall but I have stared at this so long that I think I'm getting dumber, know what I mean?
Abrium Asking the beginners questions so you don't have to! If by chance hell actually froze over and I some how helped you... Please rate.
I'll check it out, and see if we can't point you in the right direction.
Meantime, check out some new books if the one you are reading is no good. Also, look into Object Oriented Programming. It helps.
Even though you are using vs2008, there is a Book Title "Professional VB2005 by Wrox that has a very good primer on OOP, as well as some useful tidbits about VB.NET, most of which translate well into the 3.5 Framework.vs2008 area.
Again, FrmDeposit shouldn't have to know anything about FrmMain. FrmDeposit should be exposing the deposit value via a property, which you now know how to create. FrmMain calls ShowDialog and FrmDeposit does its thing. When ShowDialog returns, FrmMain gets the aforementioned property of FrmDeposit, thus getting the deposit amount. FrmMain would then presumably get the Balance property of the Account, add the deposit amount to it and then assign the new value back to the property.
In a real app the Account class would have a Deposit method that you could call and that would internally add the new deposit amount to the balance. The whole point of the Account class is to manage an account, so you shouldn't have the form adding up the new balance.
Thank you JM, thank you. I'm sucking it all in, keep it coming. So your saying complete account management should be taking place in the 'AccountClass' that makes sense to me but I must crawl before I walk and my current situation is that once FrmDeposit does its thing, no value is being transfered to the balance property. Regardless of how much I tell the damn thing to go THERE it just doesn't show. Stepping through the program the value being held from FrmDeposit drops off as soon as it is closed out. I have altered it to where the form does NOT close out. (I thought the variable and the value it held may have been being dumped). If I can get data populated into balance (from the public property) and thus on to the main form I can move on.
God bless yall that do this for a living. I just love taking the advanced classes at school so I can melt my mind every night... oh and there is that graduating thing.
Abrium Asking the beginners questions so you don't have to! If by chance hell actually froze over and I some how helped you... Please rate.
Ok It has to be a permissions issue or something because I can walk through this entire class following the Balance variable with messageboxes but NUTTIN, and I mean NUTTIN, shows up in the text field.
Observe the following code:
Code:
Sub GetData()
FrmMain.NewAccount.Balance = CInt(FrmDeposit.txtDepositAmount.Text)
MessageBox.Show(CStr(Balance))
End Sub
Sub DisplayData()
MessageBox.Show(CStr(Balance))
FrmMain.txtAccntBalance.Text = CStr(FrmMain.NewAccount.Balance)
End Sub
Both of those messageboxes provide me with the correct variable information, there has to be a, and I don't know the right terminology for it, scope, permission, or restriction on the variable that I am trying to display on a seperate form.
Thus, I have concluded, I am doing something wrong!!!
hahahah... I gotta laugh or I'll cry.
Abrium Asking the beginners questions so you don't have to! If by chance hell actually froze over and I some how helped you... Please rate.
A private member variable to a class can only be used within the scope of THAT class correct? If that is the case then how do I dump that information into another variable for read only public display without breaking data integrity?
Abrium Asking the beginners questions so you don't have to! If by chance hell actually froze over and I some how helped you... Please rate.
I have done some stuff to your project. Mind you, I am a FAN of promoting folks to dig around themselves, and NOT coding it for them. However, Not so long ago, one of our IT guys gove me some basic working code, and it was enormously helpful (plus it sounds like you are doing your best to find answers on your own . . .).
I have attached a vs Project file (sans compiled elements, so hit "Build" before you run it . . .).
Disclaimer: I do NOT claim that anything in here represents "well-thought-out" code, or even the way some of this SHOULD be done. But I tried to cover some basics, and from there, maybe you can come back and tell ME where I was an incompetent boob!
Anyway, first I reworked some of your AccountClass, and it will now handle both Deposits and withdrawls of some Integer-based currency:
Code:
Option Strict On
Imports System.IO
Public Class AccountClass
'Member variables of class
Private intBalance As Integer = 0
Public Property Balance() As Integer
Get
Return intBalance
End Get
Set(ByVal value As Integer)
intBalance = value
End Set
End Property
'A function to handle DEPOSITS:
Public Function DepositFunds(ByVal Amount As Integer) As Integer
'Going a little ape &*&# here, but a variable to hold your addition:
Dim NewBalance As Integer = intBalance + Amount
'NOTE the manipulation of the Private FIELD above, and here:
intBalance = NewBalance
'We'll return the value of intBalance to the Client (frmMain, in this case):
Return intBalance
End Function
'The reverse of the above transaction:
Public Function WithdrawFunds(ByVal Amount As Integer) As Integer
Dim NewBalance As Integer = intBalance - Amount
'Might need to handle some overdraft issues:
If NewBalance > 0 Then
intBalance = NewBalance
Else
MsgBox("Your Withdrawal has exceeed available funds. Ask Tim Geitner for a bailout!")
intBalance = NewBalance - 50 'Overdraft fee . . .
End If
Return intBalance
End Function
End Class
Now here is the frmMAIN. I added a Label and a TextBox to hold the Current Account balance (which for now will ALWAYS be zero at form load . . .):
Code:
Option Strict On
Imports System.IO
Public Class FrmMain
'Just me, but I dont initialize Private members when they are declared (usually). DId it in the Load event instead.
Public NewAccount As AccountClass
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
NewAccount = New AccountClass
NewAccount.Balance = 0
Me.txtBalance.Text = NewAccount.Balance.ToString
End Sub
Private Sub btnDeposit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDeposit.Click
Me.InitiateTrans(WindowsApplication1.TransType.Deposit)
End Sub
Private Sub btnWithdraw_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnWithdraw.Click
Me.InitiateTrans(TransType.Withdrawal)
End Sub
Private Sub InitiateTrans(ByVal TransType As TransType)
'Don't use the default instance of the form; Declare a NEW one, provide the
'Constructor parameters, and . . .
'ALSO, the USING statement means free cleanup of the
'discarded form object (Look it up):
Using frmTrans As New frmTransaction(TransType, NewAccount.Balance)
'If you don't use the SHowDialog as a function, you simply get a Modal form.
'Your original code had no way to know the form was done . . .
If frmTrans.ShowDialog = Windows.Forms.DialogResult.OK Then
'Since you are using Option Strict, you have to make sure you
'Convert to Integer (THere are newer ways to do this, but I
'Havent "unlearned" some old habits yet . . .):
Dim TransAmount As Integer = CInt(frmTrans.txtTransAmount.Text)
'Now call the local Method:
Me.ProcessTrans(TransType, TransAmount)
End If
End Using
End Sub
Private Sub ProcessTrans(ByVal TransType As TransType, ByVal TransAmount As Integer)
If TransType = TransType.Deposit Then
'On AccountClass, I set these up as FUNCTIONS which return the new balance
'When processing is complete(But once again, we have to observe the Option Strict requirement):
Me.txtBalance.Text = NewAccount.DepositFunds(TransAmount).ToString
Else
Me.txtBalance.Text = NewAccount.WithdrawFunds(TransAmount).ToString
End If
End Sub
End Class
And now the Re-worked (and Re-named) frmTransaction. I added some labels and textBoxes:
Code:
'An ENUMERATION for TransactionTypes. You will see why this is cool when you run the app:
Public Enum TransType
Deposit = 1
Withdrawal = 2
End Enum
Public Class frmTransaction
'Overloaded Constructor can accept some initial values, and have them ready when the
'form is shown:
Public Sub New(ByVal TransType As TransType, ByVal CurrentBalance As Integer)
Me.InitializeComponent()
'Just for kicks, set a Header label appropriately:
If TransType = WindowsApplication1.TransType.Deposit Then
Me.lblTransactionType.Text = "Make A Deposit"
Else
Me.lblTransactionType.Text = "Make A Withdrawal"
End If
txtAcctBalance.Text = CurrentBalance.ToString
txtTransAmount.Text = 0
End Sub
'A test to make sure the value entered in txtTransAmount will result
'in a successful transaction:
Private Function CanProcess() As Boolean
If IsNumeric(txtTransAmount.Text) Then
Return True
Else
MsgBox("You Must enter a valid cash amount, or cancel the transaction")
Return False
End If
End Function
'This event triggers the test; if the test fails, the cmdOK button will be disabled:
Private Sub txtTransAmount_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtTransAmount.Leave
btnOK.Enabled = Me.CanProcess
End Sub
'At load, the cmdOK Button is DISABLED, pending user input:
Private Sub FrmDeposit_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
btnOK.Enabled = False
txtAcctBalance.Enabled = False
End Sub
'HERE is one of the things you were missing:
Private Sub btnOK_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnOK.Click
Me.DialogResult = Windows.Forms.DialogResult.OK
End Sub
Private Sub btnCancel_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Me.DialogResult = Windows.Forms.DialogResult.Cancel
End Sub
End Class
Hope that helps. See the attached project, and let me know if you have questions. I gotta get to bed tonight, but I'll check back in the morning.
Note that there is A LOT to be desired about the code I have provided here, I threw it together on the fly, and got it to work. Now YOU make it better!
btw, you should know I am NOT a pro, and it wasn't so long ago I was going thru the same thing. Still am, actually, just with different things . . . it gets better, but not really. I once had a social life . . .
A private member variable to a class can only be used within the scope of THAT class correct? If that is the case then how do I dump that information into another variable for read only public display without breaking data integrity?
THAT is the purpose of the Public Property. You can, for example, "Reach out" from frmMain, and Grab Values from (or do things to) values within your AccountClass through the PUBLIC Properties. In the same way, when you are "done" with frmDeposit, You can grab values from the public properties of that to. It just so happens that a TextBox on frmDeposit IS a public Property of the form. Even more, the Text Property of that TextBox is ALSO a public property (of the textbox), which is a Public property of the form. See the code in my previous two posts, and play with it a little.
The problem becomes, once you begin to understand, that there are SO many different ways to do something in some cases, it's hard to figure out which way to go!