VbScript/ASP Classic good OOP Pattern [closed] - oop

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Hy all,
I have to create a website in Classic ASP, and i really want to do a clean design so i will try to put everything in Classes and Models to emulate the ViewModel Pattern.
So can you tell me if this approch of creating objects is good because i will use it everywhere
Class User
Public Name
Public Adress
Public Title
Public Text
Public Rights 'ArrayList of Right objects
Private Sub Class_Initialize()
Initialize
End Sub
Private Sub Class_Terminate()
Dispose
End Sub
Private Sub Initialize()
Name = ""
Adress = ""
Title = ""
Text = ""
Set Rights = Server.CreateObject("System.Collections.ArrayList") ' Arraylist .net
End Sub
Private Sub Dispose()
End Sub
End Class
Class Right
Public Name
Private Sub Class_Initialize()
Initialize
End Sub
Private Sub Class_Terminate()
Dispose
End Sub
Private Sub Initialize()
Name = ""
End Sub
Private Sub Dispose()
End Sub
End Class
And then i do this for instantiating objects :
Dim myUser
Set myUser = New User
'Do some work
Set myUser = nothing 'Dispose the object
Any idea, suggestion or correction is welcome.
Thanks for help.

VBScript does not support object instantiation with parameters, but you could add it like this:
Public Function [New User](name)
Set [New User] = New User
[New User].Name = name
End Function
Now you can create a user like:
Set myUser = [New User]("Arthur Dent")
Usefull when you have mandatory fields you want to set during initialization.
You can also make composites with this technique:
Public Function [New PowerUser](name)
Set [New PowerUser] = New User
[New PowerUser].Name = name
Set [New PowerUser].Rights = RightsCollection("PowerUser")
End Function
Public Function [New GuestUser](name)
Set [New GuestUser] = New User
[New GuestUser].Name = name
Set [New GuestUser].Rights = RightsCollection("Guest")
End Function

it don't see a need to create an extra function "Initialize" and "Dispose" and call that from within Class_Initialize() and Class_Terminate() respectively.
You can just put the code inside the class constructor and destructor.
Secondly, you made your members variables public, if you'd like to make your classic asp work as much object-oriented as possible you should start using getters and setters.
Thus like this:
Private m_Name
Public Property Get Name()
Name = m_Name
End Property
Public Property Let Name(sName)
m_Name = sName
End Property
With the Rights member variable you're going have more fun :)

Related

Add A Method To A Property Of A Class

I am confused. I am new to VBA classes. I want to add multiple methods to a property of a class, or add properties to another property. I may not have the terminology correct?
I can add one property, but I want to drill down deeper.
For instance if I make a class person:
PersonClass.Features.Hair.Texture.Color
PersonClass.Features.Hair.Texture.Style
PersonClass.Features.Hair.Length
I am not sure how to go about this.
e.g.
MyClass.MyProperty.MyMethod1
MyClass.MyProperty.MyMethod2
MyClass.MyProperty.MyMethod3
or
MyClass.MyProperty.MyMethod1.MyMethod2
Here is an example to illustrate the concepts mentioned in the comments:
Main Form
Option Explicit
Private Sub Form_Load()
Dim p As Person
Set p = New Person
p.Features.Hair = "Red"
MsgBox p.Features.Hair
End Sub
Person Class
Option Explicit
Private m_Features As Features
Private Sub Class_Initialize()
Set m_Features = New Features
End Sub
Public Property Get Features() As Features
Set Features = m_Features
End Property
Features Class
Option Explicit
Private m_Hair As String 'this would actually be another class
'in your example
Public Property Get Hair() As String
Hair = m_Hair
End Property
Public Property Let Hair(ByVal Value As String)
m_Hair = Value
End Property

Pass an instance of a same class in new method and replace "me"

I'm sorry but it's difficult to explain my problem.
I have a class and in the new method, I want to be able to pass an instance of the class - if an instance is passed, this instance should be used (replace 'me').
An example...
Public Class DataConnection
Implements IDisposable
Public Property SqlCnn As SqlClient.SqlConnection
Private _isNewInstance As Boolean
Public Sub New()
_isNewInstance = True
SqlCnn = New SqlClient.SqlConnection
End Sub
Public Sub New(dc As DataConnection)
_isNewInstance = False
Me = dc ' <- this is not valid
End Sub
#Region "IDisposable Support"
Private disposedValue As Boolean
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
If disposing Then
End If
If _isNewInstance Then
SqlCnn.Close()
SqlCnn.Dispose()
SqlCnn = Nothing
End If
' Do my clean up code
End If
disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
End Sub
#End Region
End Class
Then I want to be able to create new instances like this:
Dim dc As New DataConnection
Dim dc2 As New DataConnection(dc)
I need it to support "using" statement, since my real class implements iDisposable and I need to do one thing if no instance was passed and another thing is an instance was passed in the new method. So I can't use singleton.
Okay, where to start?
Me refers to the inside of the current object.
Such as a Form, Class, or other Object.
Me is shorthand and doesn't work like a pointer in C.
If you really want to copy properties of two classes, you should either implement a .Copy Sub or do it outside of the class.
Have you tried
Public Function CopyAnObject(ByVal Source as Object) as Object
CopyAnObject = Source
End Function
I'm confused what the use case for this could be, but seems like you're trying to hack something which isn't worth hacking?
Can the OP provide any more information on what s/he wants to achieve?
If you're really desperate to hack it, convert the whole Class into an IO.MemoryStream and hack it from there.

Does setting an object to nothing also set it's child objects to nothing?

Say I have an object, Email, one of whose properties is an object called EmailSkinner.
The EmailSkinner is instantiated in the class_initialize subroutine like this.
private sub class_initialize()
set EmailSkinner = new MyEmailSkinner
end sub
Must I explicitly set the EmailSkinner object to nothing in the class_terminate subroutine of Email?
private sub class_terminate()
set EmailSkinner = nothing
end sub
Or does this happen automatically when I set the Email object itself to nothing?
This is an interesting question. Your assumption is correct any object's you instantiate inside the scope of the parent class will be released when the parent class is released from memory.
However as with all object instantiation in VBScript (and by extension Classic ASP) there is nothing wrong with explicitly releasing objects using the Class_Terminate event.
Remember though that "scope" is important here.
If your EmailSkinner object reference is declared outside of the parent class (regardless of whether it is instantiated inside the class) the reference will remain and will require Class_Terminate() to force the object reference to be released.
Examples
Object Reference is declared inside Class scope.
Class ParentObject
Private _ChildObject
Private Sub Class_Initialize()
Set _Object = new ChildObject()
End Sub
End Class
Object Reference is declared outside Class scope (wouldn't recommend this approach).
Dim GlobalObject
Class ParentObject
Private Sub Class_Initialize()
Set GlobalObject = new ChildObject()
End Sub
'GlobalObject reference will remain so we need to
'force it to be released.
Private Sub Class_Terminate()
Set GlobalObject = Nothing
End Sub
End Class
By default, Class objects are auto destroyed, but if you create new objects outside, you will need to release them from memory .
Is always recommended that we clean memory in all scenarios .
I made a small piece of code for you to test ( I hope this would be similar to what you are trying to explain, since you didn't show us your code ) .
This code help us to check if something remains in memory after some steps of execution and declaration ( just take out the apostrophes at bottom to test the code ) :
Class EmailSkinner
public color
public size
Private Sub Class_Initialize
color = "blue"
size = 300
End Sub
End Class
Class Email
public details
public name
Private Sub Class_Initialize
Set details = New EmailSkinner '//Module Scope
End Sub
Private Sub Class_Terminate
Set details = Nothing
End Sub
End Class
Set email1 = New Email '//Global Scope
With email1
.details.color = "black"
.details.size = 400
End With
''//Take out the apostrophe to test one of the next lines
'Response.Write email1.details.color '//ASP only
'wscript.echo email1.details.color '//Wscript only
Set email1 = Nothing

Using collections as properties of an object in VBA

With class module "Class1Test" as
Private pGreetings As Collection
Public Property Get Greetings() As Collection
Greetings = pGreetings
End Property
Public Property Let Greetings(Value As Collection)
pGreetings = Value
End Property
If I run the sub
Dim MyPhrases As Class1Test
Public Sub Test()
Set MyPhrases = New Class1Test
MyPhrases.Greetings.Add "Have a nice day"
End Sub
I get the a compile error "Argument not optional"
Why can't I add the string to the the collection myphrases.greetings ? Please forgive the newbie question. Just learning VBA.
A few things wrong.
Collection is an object, so you must use the Set keyword when assigning. Also in the Let procedure for consistency in naming conventions, I would use lGreetings instead of Value although that should not really matter.
Private pGreetings As Collection
Public Property Get Greetings() As Collection
Set Greetings = pGreetings
End Property
Public Property Let Greetings(lGreetings As Collection)
Set pGreetings = lGreetings
End Property
This will still raise an 91 error (Object variable or with block not set) because you have not instantiated the collection object. Probably the way you should do this is in the class module's Initialize routine.
Private Sub Class_Initialize()
Set pGreetings = New Collection
End Sub

Best way to expose an object with read-only properties only

I can't find an answer to my question so I'm asking a new one.
I have an object where I want to fill it's properties from another class in the same solution. But the object should expose read-only properties only so the outside-caller can't see nor access the setter (cause there is no setter).
What is the best way to fill the internal backing variables from the same solution? I know I could do it in the constructor but I want to be able to set the variables after creating the object.
Sorry for my weird explaination, maybe a bit of code could help.
This is what I'm doing now:
Public Class ReadonlyObject
Protected Friend Sub New()
End Sub
'Could use this, but don't want to...
Protected Friend Sub New(foo As String)
End Sub
Friend _foo As String
Public ReadOnly Property Foo As String
Get
Return _foo
End Get
End Property
End Class
Public Class FillReadonlyObject
Private Sub DoSomeHeavyWork()
Dim roObject As New ReadonlyObject
roObject._foo = "bar"
'Could use this, but don't want to...want to access properties directly.
Dim roObject2 As New ReadonlyObject("bar")
End Sub
End Class
With this, the ReadonlyObject's properties are correctly exposed as readonly but I'm afraid it's bad practice.
I've seen implementations like this:
Public Class ReadonlyObject
Protected Friend Sub New()
End Sub
Private _foo As String
Public Property Foo As String
Get
Return _foo
End Get
Friend Set(value As String)
_foo = value
End Set
End Property
End Class
Public Class FillReadonlyObject
Private Sub DoSomeHeavyWork()
Dim roObject As New ReadonlyObject
roObject.Foo = "bar"
End Sub
End Class
This works, but exposes the property with a setter. It's not accessible, but it's visible and I don't want that :)
So maybe it's only a cosmetic thing but I think it's nice to tell the caller (or at least intellisense) the property is strictly read-only.
Thanks, Jan
If you want to explicitly declare the property as read-only, but then still have a way to set it after it is constructed, then all you need to do is create your own setter method rather than using the one automatically created for you but the property. For instance:
Public Class ReadonlyObject
Protected Friend Sub New()
End Sub
Private _foo As String
Public ReadOnly Property Foo As String
Get
Return _foo
End Get
End Property
Friend Sub SetFoo(value As String)
_foo = value
End Sub
End Class
Public Class FillReadonlyObject
Private Sub DoSomeHeavyWork()
Dim roObject As New ReadonlyObject
roObject.SetFoo("bar")
End Sub
End Class
Or, you could create two properties, like this:
Public Class ReadonlyObject
Protected Friend Sub New()
End Sub
Public ReadOnly Property Foo As String
Get
Return HiddenFoo
End Get
End Property
Friend Property HiddenFoo As String
End Class
Public Class FillReadonlyObject
Private Sub DoSomeHeavyWork()
Dim roObject As New ReadonlyObject
roObject.HiddenFoo = "bar"
End Sub
End Class