Override a Function - vba

The following "aMacro" returns the error "Ambiguous name Detected" I understand why. Anybody know a way to override the first definition and and only use the definition inside of the function so that aFunction will return x - y ?
Besides changing the name.
Function aFunction(x As Integer, y As Integer) As Integer
aFunction = x + y
End Function
Sub aMacro()
Function aFunction(x As Integer, y As Integer) As Integer
aFunction = x - y
End Function
MsgBox aFunction(4, 3)
End Function

A function can be Private or Public, but the scope is always the whole module.

This can simulate "override function" with 4 class modules:
Functions, IFunction, FunctionAdd, FunctionSubtract.
class module Functions:
Function aFunction(x As Integer, y As Integer) As Integer
aFunction = x + y
End Function
interface IFunctions:
Function aFunction(x As Integer, y As Integer) As Integer
End Function
class module FunctionAdd:
Implements IFunctions
Private mFunctions As Functions
Private Sub Class_Initialize()
Set mFunctions = New Functions
End Sub
Private Sub Class_Terminate()
Set mFunctions = Nothing
End Sub
Private Function IFunctions_aFunction(x As Integer, y As Integer) As Integer
IFunctions_aFunction = mFunctions.aFunction(x, y) ' Uses the standard aFunction
End Function
Class module FunctionSubtract:
Implements IFunctions
Private mFunctions As Functions
Private Sub Class_Initialize()
Set mFunctions = New Functions
End Sub
Private Sub Class_Terminate()
Set mFunctions = Nothing
End Sub
Private Function IFunctions_aFunction(x As Integer, y As Integer) As Integer
IFunctions_aFunction = x - y ' Override aFunction, subtract values
End Function
You can test this with this:
Dim f As IFunctions
Set f = New FunctionAdd: Debug.Print f.aFunction(1, 2)
Set f = New FunctionSubtract: Debug.Print f.aFunction(1, 2)
Of course this is tedious for one function.
I could be useful is you have a lot of functions to override in many classes.

Try adding in the Optional value in the function. If the optional value isnt included in the call then it wont be references in the function.
Function aFunction(x As Integer, y As Integer, Optional override As Boolean) As Integer
If Not override Then
aFunction = x + y
Else
aFunction = x - y
End If
End Function
Sub aMacro()
MsgBox aFunction(4, 3)
MsgBox aFunction(4, 3, True)
End Sub

Related

referencing VisualBasic methods

In VB, I want to assign a (shared) method to a variable
And I'm asking if there is some namespace operator like :: in C++ and Java
Class C
Public Shared Function m(a as Integer) as Integer
Return a * 2
End Function
End Class
Public Sub Main()
Dim localM As Func(Of Integer, Integer) = C.m
Console.WriteLine(localM(5))
End Sub
I know I could use function(a) C.m(a)
but that is not pretty
and I don't want to create a new function every time
and is also sensitive to argument changes
as for why would I do that
I'm actually passing it to function as an argument
(someFunction(3, C::m))
You can do this:
Sub Main()
Dim localM As Func(Of Integer, Integer) = AddressOf C.m
Console.writeline(localM(5))
End Sub
You can see it work here:
https://dotnetfiddle.net/Uxl0Y7
I didn't change anything in the sample class, except to complete the function so it returns a value (required for the function to compile) and to fix your lousy capitalization.
I'm actually passing it to function as an argument
In that case:
Sub Main()
Dim localM As Func(Of Integer, Integer) = AddressOf C.m
Foo(localM)
' Or
Foo(AddressOf C.m)
End Sub
Sub Foo(theMethod As Func(Of Integer, Integer))
Console.WriteLine(theMethod(5))
End Sub
In either case, the trick is to do two things:
Define either an Action (for a Sub) or Func (for a Function) that matches the signature of the target method. In this case, it's Func(Of Integer, Integer). Any method up to 8 arguments can be mapped this way, but you do have to know the signature in advance.
Use AddressOf to capture the reference to the method.
Is this what you are looking for?
Class C
Public Shared Add1 As Func(Of Integer, Integer) = Function(value As Integer)
Return value + 1
End Function
End Class
to use
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim foo As Integer = C.Add1(3)
Debug.WriteLine(foo)
End Sub
edit
Class C
Public Shared Add1 As Func(Of Integer, Integer) = Function(value As Integer)
Return value + 1
End Function
Public Shared DebugStr As Action(Of String, String) = Sub(first As String, second As String)
Debug.WriteLine("One-{0} Two-{1}",
first, second)
End Sub
End Class
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim foo As Integer = C.Add1(7)
Debug.WriteLine(foo)
C.DebugStr("Quick", "Fox")
End Sub

How to use variable value to access class member in vb.net

Not sure if this is possible:
i want to create a sub with 2 inputs a
Public sub testsub(byval x as string,byval y as string)
dim z as class specialdevicelcass
z.y = x
end sub
is this even posible, y variable will always be a member of the special device class
You can use reflection for this:
Public Sub testsub(ByVal x As String, ByVal y As String)
Dim z As New specialdevicelcass
Dim prop = z.GetType.GetProperty(y)
prop.SetValue(z, x)
End Sub

Create deep copy of object [duplicate]

This question already has answers here:
Deep cloning objects
(58 answers)
Closed 6 years ago.
I need help with the deep copying of objects in VB.net. I am aware of the fact that there is a great amount of topics dealing with that, but I was not able to adapt it to my problem. So hopefully someone can explain it to me using my code.
The problem: I have designed a class clsParameter which has one name, one unit, one value type and one value. The value can be a double or an object of type clsVectorParameter with the properties X,Y,Z. Now I want to do a deep copy of a parameter so that X,Y,Z are also copied.
Here are the two classes. The clone function below just represents a dummy. I know that it doesn't work like this but I didn't know a better way...
Public Class clsParameter
' Using the ICloneable interface
Implements ICloneable
' Variable definition
Private m_Name As String
Private m_Unit As String
Private m_Type As String
Private m_Value As Object
' Define set and get methods
Public Property Name As String
Get
Return m_Name
End Get
Set(ByVal value As String)
m_Name = value
End Set
End Property
Public Property Unit As String
Get
Return m_Unit
End Get
Set(ByVal value As String)
m_Unit = value
End Set
End Property
Public Property Value As Object
Get
Return m_Value
End Get
Set(ByVal value As Object)
m_Value = value
End Set
End Property
Public Property Type As String
Get
Return m_Type
End Get
Set(ByVal value As String)
m_Type = value
End Set
End Property
' Define constructor
Public Sub New(ByVal p_Name As String, ByVal p_Unit As String, ByVal p_Value As Object, ByVal p_Type As String)
m_Name = p_Name
m_Unit = p_Unit
m_Type = p_Type
m_Value = p_Value
End Sub
' Define Clone function to create independent copies of parameter instances
Public Function Clone() As Object Implements System.ICloneable.Clone
Dim cloneParam As New clsParameter(m_Name, m_Unit, m_Value, m_Type)
Return cloneParam
End Function
End Class
and the other class:
Public Class clsVectorParameter
Implements ICloneable
' Variable definition
Private m_x As Double
Private m_y As Double
Private m_z As Double
Public Property X As Double
Get
Return m_x
End Get
Set(ByVal value As Double)
m_x = value
End Set
End Property
Public Property Y As Double
Get
Return m_y
End Get
Set(ByVal value As Double)
m_y = value
End Set
End Property
Public Property Z As Double
Get
Return m_z
End Get
Set(ByVal value As Double)
m_z = value
End Set
End Property
' Define constructor
Public Sub New(ByVal p_x As Double, ByVal p_y As Double, ByVal p_z As Double)
m_x = p_x
m_y = p_y
m_z = p_z
End Sub
' Define Clone function to create independent copies
Public Function Clone() As Object Implements System.ICloneable.Clone
Dim cloneVecParam As New clsParameter(m_x, m_y, m_z, "Vec")
Return cloneVecParam
End Function
End Class
I use the class in this line:
Dim aNewParam As New clsParameter("Name", "Unit", New clsVectorParameter(x,y,z), "Type")
or
Dim aNewParam As New clsParameter("Name", "Unit", Double, "Type")
Later I need to create a deep copy of this aNewParam, so the x,y,z values are also independent for all parameters.
Thank you very much for your help!
Best regards,
Sebastian
Public Sub New(ByVal p_Name As String, ByVal p_Unit As String, ByVal p_Value As Object, ByVal p_Type As String)
m_Name = p_Name
m_Unit = p_Unit
m_Type = p_Type
If TypeOf (p_Value) Is Double Then
m_Value = p_Value
ElseIf TypeOf (p_Value) Is clsVectorParameter Then
m_Value = p_Value.Clone()
End If
End Sub
To keep your code in line with for example creating a clone of an XElement, do this from the constructor:
Dim obj1 = new clsVectorParameter(1, 1, 1)
Dim obj2 = new clsVectorParameter(obj1)
So now you only need to write an overloaded constructor, and there is no need for interfaces or seperate functions.
An overloaded constructor can be made like this: (you need to adapt this to your own class):
Public Class Foo
Dim x As Integer
Dim y As Integer
Dim z As Integer
Sub New(a As Integer, b As Integer, c As Integer)
x = a
y = b
z = c
End Sub
Sub New(old As Foo)
x = old.x
y = old.y
z = old.z
End Sub
End Class

Iterate through a dictionary of Subs/Functions and call them

I'm trying to get the pointer to a function (like in C++) in VB.net and add it to a dictionary to be called later. I have no idea how to do this in VB but I know it's easily done in C++ using void*. I really want to avoid having 8000 global variables such as nextTime_RunSub1, nextTime_RunSub2, etc with a very big Select Case or If statement.
For example:
Public dictOfNewThinkFuncsToAdd As New Dictionary (Of ?, Single) 'Function/Sub, Time To Call
Private Sub Main()
Dim dictOfThinkFuncs As New Dictionary (Of ?, Single) 'Function/Sub, Time To Call
dictOfThinkFuncs.Add(AddressOf(Sub1), GetCurrentTime() + 5)
dictOfThinkFuncs.Add(AddressOf(Sub2), GetCurrentTime() + 6)
Dim removalQueue As New List(Of ?)
Do
Dim bRemoveFunc As Boolean = False
Dim bAddFunc As Boolean = False
For iter As Integer = 0 To dictOfThinkFuncs.Count - 1
If GetCurrentTime() >= dictOfThinkFuncs(iter).Value Then
CallFunction(dictOfThinkFuncs(iter).Key)
removalQueue.Add(dictOfThinkFuncs(iter).Key)
bRemoveFunc = True
End If
Next
If bRemoveFunc Then
For Each func In removalQueue
dictOfThinkFuncs.Remove(func)
Next
removalQueue.Clear()
End If
For Each func In dictOfNewThinkFuncsToAdd
dictOfThinkFuncs.Add(func.Key, func.Value)
bAddFunc = True
Next
If bAddFunc Then
dictOfNewThinkFuncsToAdd.Clear()
End If
Threading.Thread.Sleep(10)
Loop
End Sub
Private Sub Sub1()
DoStuff()
dictOfNewThinkFuncsToAdd.Add(AddressOf(Sub3), GetCurrentTime() + 15)
End Sub
Private Sub Sub2()
DoStuff()
dictOfNewThinkFuncsToAdd.Add(AddressOf(Sub2), GetCurrentTime() + 15)
End Sub
Private Sub Sub3()
DoStuff()
End Sub
This work (both formats). So you can either wrap your calls inside a uniform return or just do addressOf if they are all same type of function with no params.
It's not exactly your code (I know... I know). But gives you a quick example of a dictionary of Lambda functions. And it's vb.net.
Option Strict On
Module Module1
Sub Main()
Dim getters As New Dictionary(Of String, Func(Of Boolean))
getters.Add("First", New Func(Of Boolean)(Function()
Console.WriteLine("Test Run")
Return true
End Function))
getters.Add("Second", AddressOf TestMe)
For each el In getters.Values
el()
Next
End Sub
Public function TestMe() As boolean
Console.WriteLine("Test Run")
Return true
End function
End Module
Dictionary(of Action, Single) works too...
I guess you can do that without the return parameter, too (the vb.net equivalent of void function() is Sub() which is an object of type Action as seen below).
Module Module1
Sub Main()
Dim getters As New Dictionary(Of String, Action)
getters.Add("First", New Action(sub()
TestMe()
End sub))
getters.Add("Second", AddressOf TestMe2)
For each el In getters.Values
el()
Next
End Sub
Public Sub TestMe2()
Console.WriteLine("Test Run")
End Sub
Public function TestMe() As boolean
Console.WriteLine("Test Run")
Return true
End function
End Module

Passing variables from one procedure to another

How can I use a vairable from Sub Main, in another sub.
Example
Sub Main()
Dim x As Long
End Sub
Sub Test() Dim y = x End Sub
Is this possible on vb.net
You could pass it to a function and return it again:
Sub Main()
Dim x As Long
' Give x a value
x = Test(x)
' Do something else with x
End Sub
Function Test(x As Long) As Long
' Do something with x
Return x
End Sub
Or declare it as a global variable:
Dim x As Long
Sub Main()
' Do something with x
End Sub
Sub Test()
Dim y = x ' Do something else
End Sub
There is a very easy way to do this.
Declare the value out of all the Subs on the top.
Public Class Form 1
Dim x As Long
Private Sub Main ()
End Sub
Private Sub Test ()
End Sub
End Class
And then write y = x on whichever Sub you want!