I have a File class that has an
Open() method.
I have a subclass
of File called TextFile that
implements an IReadableFile
interface, which requires the
implementation of a Read() method.
If I declare a variable myFile as IReadableFile, I can't call the Open() method on it. I want to be able to exercise the functionality of TextFile's base class (File) methods and its interface (IReadableFile) methods at once. Is this possible?
EDIT: I'm working in VB.NET (if that matters).
I'm trying to provide a minimum set of File I/O functionality via a File class and then provide extended capabilities for particular types of files by deriving from File and adding some additional methods (like Read, Write, etc.). I want the derived classes to be polymorphic - e.g., calling the Write method on a TextFile will simply write the text data to the filesystem, whereas calling the Write method on a BinaryFile might base 64 encode the binary data before writing it to the filesystem.
Create an IFile interface, make the File class implements IFile. The IReadableFile will inherits from IFile.
Its only possible if you put Open() in IReadableFile or cast your IReadableFile to a TextFile.
More details about what you're doing might help.
You can declare myFile as a TextFile object. Then you will be able to call Read (from the inherited File object) and Open (from the implemented IFileReadable interface).
Public Class File
Public Sub Open()
End Sub
End Class
Public Interface IFileReadable
Sub Read()
End Interface
Public Class TextFile
Inherits File
Implements IFileReadable
Public Sub Read() Implements IFileReadable.Read
End Sub
End Class
Public Class Main
Public Sub New()
Dim oFile As TextFile
oFile.Read()
oFile.Open()
End Sub
End Class
Related
I have written a VB.NET class that has COM Interop enabled so it can be utilized in VBA - specifically, MS Access.
The class works fine in VB.NET.
With Accees, I can add the reference to it, instantiate the main object and set and return some properties.
But Access does not recognize anything relating to the sub-classes underneath the main class. VB.NET has no problem exposing these classes, but not VBA.
Is this simply a limitation of COM Interop and/or VBA?
Is there a work-around?
No you can’t get interop to generate the sub classes for you (to appear in VBA)
However, keep in mind that nested classes are really the same as non-nested. That sub class instance HAS to be initialized anyway. And there is nothing you can't do if the classes were to be separated. And you can well place many classes in one code module.
So this is purely a syntax preference you are looking for.
However, what you can do declare a pubic instance of any sub class in the main class (variables area as public).
Take this simple example.
Imports System.Runtime.InteropServices
<ClassInterface(ClassInterfaceType.AutoDual)>
Public Class Class1
Private m_Company As String = ""
Public Function MyHello()
MsgBox("Hello world")
End Function
Public Property Company As String
Get
Return m_Company
End Get
Set(value As String)
m_Company = value
End Set
End Property
<ClassInterface(ClassInterfaceType.AutoDual)>
Public Class Class2
Private m_FirstValue As Integer = 2
Public Property V1 As Integer
Get
Return m_FirstValue
End Get
Set(value As Integer)
m_FirstValue = value
End Set
End Property
Public Function MyTimes2() As Integer
Return m_FirstValue * 2
End Function
End Class
End Class
NOTE above the nested class “class2” in above.
Ok, so check the make com assembly visible = True, and for testing check the “register for com interop”
Compile the above, set the reference in Access. (Note how you don’t have to build a custom interface either!!!).
Now, in VBA you get this in intel-sense.
NOTE carefully how the sub class Class2 does not appear.
If you really want the intel-sense and sub class to appear, then to the above vb.net class, simple add this;
Public Class Class1
Private m_Company As String = ""
Public SClass2 As New Class2 <--- add this line to expose as public
Private m_Company As String = ""
.etc. etc. etc.
Now I put a “S” in from of the name – you unfortunately can’t use the same name as the nested class. (so either put something in front of the nested class, or something in front of the public instance of that class (that is what I did in above).
Now if we compile, then in VBA you get this:
Note the class2 DOES appear as a sub class
And if I hit a “dot” in VBA editor, then the sub class methods show like this:
So quite sure the above is the only way to get the sub-classes working with COM interop
I have a pretty big VB.net code and I am trying to split it into different files. I want to create an external file containing different functions. I have read about partial class files but it is not working for me. Is there any option to call/import a vb.net file and do something as per below example?
Example
Form1.vb
' Imports Functions.vb (How can I call the file containing the class?)
Public Class Form1
Dim a,b,y As Double
Dim calculate As New MyFunctions
a=1
b=1
y=calculate.sum(a,b)
End Class
Functions.vb
Partial Class MyFunctions
Public Function sum(a As Double, b As Double) As Double
return a+b
End Function
End Class
If you want all the functions to be available to all your code, just create a module with the functions in them.
If you just want to split your form1 class into separate files, your form1 file should contain the class definition ..
Partial Public Class Form1
To create a new file for the bits you want to separate off, create a new class file and change the default definition to the above.
Please note that you might need to add Imports lines for each files as well.
In and old project of mine, I had a single form program but had the code split into several files such as ExcelFileHandling.vb, EmailHandling.vb etc. They were all actually partial definitions of Form1. Easy peasy :-)
You use the Imports statement when you don't want to fully qualify a namespace of a class. If the other class is in the same namespace as the class that is referencing it, there is no need to use Imports.
Note, that your example code has functionality that should exist in a method instead of in the body of the class.
'RootNamespace = Right click on project file and choose properties. You'll see it defined there.
Imports RootNamespace.SomeOtherNamespace
Namespace SomeNamespace
Public Class Form 1
Public Sub SomeMethod()
Dim objMyFunctions As New MyFunctions()
'If no Imports is used: As New SomeOtherNamespace.MyFunctions()
End Sub
End Class
End Namespace
Namespace SomeOtherNamespace
Public Class MyFunctions
End Class
End Namespace
Example if both classes are in the same Namespace:
Public Class MyFunctions
Public Sub SomeMethod()
'No need for Imports because they are in the same Namespace.
Dim objMyFunctions As New MyFunctions()
End Sub
End Class
Public Class MyFunctions
End Class
I collected different derived class instances using a List(Of Interface).
And naturally I only can access the Interfaced methods using iteration.
Public Class Base
Public Sub Work_inBase()
End Sub
End Class
'--------------------------
Public Interface MyIFC
Sub Work()
End Interface
'--------------------------
Public Class Child1
Inherits Base
Implements MyIFC
Public Sub Work() Implements MyIFC.Work
End Sub
End Class
'--------------------------
Public Class Child2
Inherits Base
Implements MyIFC
Public Sub Work() Implements MyIFC.Work
End Sub
End Class
'--------------------------
Public Sub MainProgram()
Dim C1 As New Child1()
Dim C2 As New Child2()
Dim MyList As New List(Of MyIFC)
MyList.Add( C1 )
MyList.Add( C2 )
MyList(0).Work() >>> OK because it was interfaced
MyList(0).Work_inBase() >>> does not work, cannot access to base
End Sub
Is there any other way to access to base class methods or members (which will be very large)??? Maybe different class design is required???
Thank you (vb is prefered, but I can read c# code equally too)
Obviously there is no way to know that an arbitrary List(Of MyIFC) actually contains members that are or do inherit type Base, so there's no reason that there should be any standard functionality that would give you items of that type. If you know for a fact that the items will be that type though, you can simply cast as that type when they come out, e.g.
DirectCast(MyList(0), Base).Work_inBase()
Of course, once you have a reference of type Base then you can't access members of MyIFC because Base doesn't implement that interface. Your example is very contrived so there's no way for us to know whether there's a better design possible in your specific case.
I have an interface IValidator, and I want classes that implement IValidator to have access to a shared set of properties and methods, but it seems VBA doesn't have true implementation inheritance, so instead I have a class BaseValidator with the shared resources, which is used as a delegate in the subclasses.
Interface:
'IValidator
Public Function isValid(columnName As String) As Boolean
End Function
'used for initializing delegate
Public Sub setup(fieldsDict As Dictionary)
End Sub
Base class:
'BaseValidator
Public fieldsDict As Dictionary
Public Sub setup(fieldsDict As Dictionary)
Set Me.fieldsDict = fieldsDict
End Sub
Public Function doSomethingWithFieldsDict(columnName as string) as variant
'do something
End Function
Example implementation:
'Validator_FeatureNumber
Private bv As New BaseValidator
Implements IValidator
Public Sub IValidator_setup(fieldsDict As Dictionary)
bv.setup fieldsDict
End Sub
Function IValidator_isValid(columnName As String) As Boolean
IValidator_isValid = IsNumeric(bv.doSomethingWithFieldsDict(columnName))
End Function
This works, but it means I have to duplicate the IValidator_setup() code block in every implementation, which seems like a bad idea for code maintainability. Is there any way to have a subclass inherit methods from a superclass in VBA?
The short answer is no.
Welcome to the the fun and exiting world of 1991:) VBA is a subset of VB6. Inheritance was not supported at that time, and because Microsoft based VBA on VB6 and then abandoned* it when they went to .Net, that means it likely never will be:(
*They did update it somewhat to cope w/64 bit API calls, but that was pretty much it.
I hope this isn't a stupid question, I can't find a reasonable answer on google.
I'm starting a project which only contains one class file. I will be turning the class file into a dll at the end. I understand that another app normally makes calls to the dll once it's referenced in the project. I need the dll to run a sub inside of it on load like a normal mybase.load sub. This sub needs to execute only once on load to populate some variables. I don't want to have to call the sub from the main app. The rest of the functions/subs in the dll will be called from the main app when needed. Please don't respond with register them globally under the class, I need a sub or function.
If there isn't such a sub how would I go about creating a function/sub that preforms an onload?
Thanks. :)
Hope I'm making sense. Thanks for your response.
Shared Sub New()
on your class.
Another option is to have a private class inside your class and initialise it with a member variable:
Public Class MyLibraryClass
Private mobjSettings As New SettingsClass
Public Function SampleLibraryFunction() As String
Return mobjSettings.SettingsProperty
End Function
Private Class SettingsClass
Friend SettingsProperty As String
Sub New()
'initialise
SettingsProperty = "This is a test"
End Sub
End Class
End Class