I need all my TableAdapters to implement a custom interface. The problem is that some of the members defined by the interface reside in the DataSet's designer file, which I don't want to (and shouldn't) alter, as that code will be regenerated automatically. I can't relocate those members to my code file either for the same reason. What's my way out of it?
When you implement an interface, the members you declare do not have to have the same names as the members of the interface and they don't have to be public. Let's say that you have this designer-generated class:
Partial Public Class SomeClass
Public Sub FirstMethod()
Console.WriteLine("FirstMethod")
End Sub
Public Sub SecondMethod()
Console.WriteLine("SecondMethod")
End Sub
End Class
and you want it to implement this interface:
Public Interface ISomeInterface
Sub FirstMethod()
Sub ThirdMethod()
End Interface
Notice that the interface has a method named FirstMethod but SomeClass already has a method named FirstMethod. You can add your own partial class to implement the interface like this:
Partial Public Class SomeClass
Implements ISomeInterface
Private Sub FirstMethodInternal() Implements ISomeInterface.FirstMethod
Me.FirstMethod()
End Sub
Public Sub ThirdMethod() Implements ISomeInterface.ThirdMethod
Console.WriteLine("ThirdMethod")
End Sub
End Class
The method that implements ISomeInterface.FirstMethod is not named FirstMethod so it doesn't clash with the existing method with that name and it is also Private so it cannot be accessed from outside using a reference of type SomeClass. Using a reference of type ISomeInterface is another matter though. If you use code like this:
Dim sc As ISomeInterface = New SomeClass
sc.FirstMethod()
sc.ThirdMethod()
you'll find that the FirstMethodInternal method of your SomeClass object gets invoked and, in turn, invokes the FirstMethod method of the same object. Try running that code and placing breakpoints on the FirstMethod and FirstMethodInternal methods to prove it to yourself.
Related
I have a few dozen classes which all implement the same interface and many of the methods have identical implementation. I have to do a lot of copy and paste whenever I add a new class. How can I get less code duplication?
I've heard that you should put the common code in a helper class but a lot of these methods are really trivial so calling a helper method is barely any simpler than doing the actual work.
Inheritance would save re-declaring all these methods but it would make it messy for the few classes that don't have the identical implementation.
Examples:
Identical in nearly every class...
Public Sub ThingWasDeleted(ByVal deletedThing As Thing) Implements Iinterface.ThingWasDeleted
If MyThing Is deletedThing Then
MyThing = Nothing
End If
End Sub
...but occasionally different:
Public Sub ThingWasDeleted(ByVal deletedThing As Thing) Implements IInterface.ThingWasDeleted
'Do nothing
End Sub
Identical in every class but already just as simple as calling a common helper method:
Public ReadOnly Property DisplayName() As String Implements IInterface.DisplayName
Get
Return DisplayNameShared
End Get
End Property
If you put these methods in a helper class, wouldn't that make it just as messy (if not more) than having an abstract base class where you can override the base class's functionality when needed?
For example:
Public MustInherit Class BaseClass
Public ReadOnly Property DisplayName() As String
Get
Return DisplayNameShared
End Get
End Property
Public Overridable Sub ThingWasDeleted(ByVal deletedThing As Thing)
If MyThing Is deletedThing Then
MyThing = Nothing
End If
End Sub
End Class
This provide a definition of the property that all inheriting classes can use, and gives the inheriting class an option to override and create their own implementation of ThingWasDeleted.
For example:
Public Class MyClass
Inherits BaseClass
Public Overrides Sub ThingWasDeleted(ByVal deletedThing As Thing)
' Do nothing
End Sub
End Class
On the other hand, if you wrote a helper class, you'd have to define every method, and the developer (which may or may not be you) would have to know which method to change. Additionally, instead of having the option to use the existing functionality in the base (abstract) class, every class you create will have to call each of the proper helper methods.
Personally, I prefer the former option, mainly because the inheriting classes don't have to call anything to get the base functionality established in the base class, and can override what they need to on a case-by-case basis. Conversely, having them all in a helper class means you have to at least write the code to call each of the necessary helper methods in every class you have.
I am trying to implement a mySubClass.vb file as a nested subclass of another main class. It seems like the Partial Class idea is what I need but the implementation isn't working when I try to pull mySubClass.vb in as a nested subclass of another main class.
My original implementation of this code used mySubClass directly so I know the functionality works. I just want to use mySubClass as a data structure within clsMain.
Main Class
Public Class clsMain
Public Property myIntProp as Integer
Public property myStrProp as String
'other properties
Partial Public Class MySubClass
'I want this functionality to be accessible via clsMain.MySubClass
'Just like any other property or function of clsMain
'Partial would keep things organized nicely
End Class
End Class
Sub Class
The class.vb that I want to use as clsMain.MySubClass.
File: MySubClass.vb
Partial Public Class MySubClass
Inherits BaseCollection
Private Class MySubSubClass '(Used for custom properties and functions)
'More properties and Functions
End Class
End Sub
Public Class BaseCollection 'functionality of MySubClass
Public Function MyFunction1()
'Return Data
End Function
End Class
How Main Class is Used
Public Class UsageClass
Private myMainDataStructure as new clsMain
Private Sub GetSubClassList()
dim MyData as ArrayList = myMainDataStructure.MySubClass.MyFunction1()
'^^^ error on this line: MyFunction1() is not a member of project.clsMain.MySubClass^^^
End Sub
End Class
Instead of trying to make this a Partial Class, you should just make a Property containing an instance of that class.
Nested classes must be created and have instances, just like top level classes. By making a property within your main class, you can automatically create that instance in your main class constructor, and your code will work as expected.
Public Class clsMain
Public Property myIntProp as Integer
Public property myStrProp as String
'other properties
Public Property OtherFunctionality as MyOtherClass = New MyOtherClass()
Then just define the class in a separate file:
Public Class MyOtherClass
Public Sub MyFunction1()
Folks;
Code looks like:
Public Class MasterA
Inherits Underling
End Class
Public Class MasterB
Inherits Underling
End Class
Public Mustinherit Class Underling
Sub DoSomething()
Me.GetType 'Using the instance, I can get the class.
end sub
Shared function() as ???? 'How can I define the return type based on the class that inherited me?
'Me.GetType 'Won't work as this is a shared function with no instance 'Me'
End Function
End class
OK. The question is: is there a way to get at the class type from within a shared function that was inherited by another class?
What I'm building is an XML serializer/desrializer as an inheritable class so that classes that inherit it can be serilized to an XML file, and back again. Rather than writing a serializer/deserializer for each type of class I want to do this with, I'd like to just inherit the functionality.
To do that, though, requires that I be able to ascertain the clas that inherited me in the shared function.
You could get the desired behavior with a generic base class, my VB is a little rusty so you might find stray parens or brackets. This would really be the only way to get a type reference to an inheriting class in a shared base class function.
Public Mustinherit Class Underling(Of T)
Sub DoSomething()
Me.GetType 'Using the instance, I can get the class.
end sub
Shared function() As T
' GetType(T) should get the type at this point
End Function
End class
Public Class MasterA
Inherits Underling(Of MasterA)
End Class
Public Class MasterB
Inherits Underling(Of MasterB)
End Class
As a side note it does seem like a rather weird solution to handle XmlSerialization rather than through your own serializer implementation or XmlSerializer
I'm refactoring, and have run into a roadblock.
Background:
I have a base class and several inherited derived classes. The derived classes don't always need to have the same properties. If any properties are shared among the derived classes, those properties would live at the base class level ('Contents', for example).
Similarly, GoodDocument below has 'GoodThings' but would not want/need to have 'BadThings'.
I want to treat instances of both 'GoodDocument' and 'BadDocument' as type 'Document'
public mustinherit class Document
public property Contents as string
public sub new()...
end class
public class GoodDocument
inherits Document
public property GoodThings as string
public sub new()...
end class
public class BadDocument
inherits Document
public property BadThings as string
public sub new()...
end class
The 'DocumentWriter' class will also have several derived classes: ('GoodDocumentWriter' and 'BadDocumentWriter').
I need to pass around the DocumentWriter.Doc as a 'Document' to a number of other places in the code. Doc.GoodThings would only be called from within an instance of either 'GoodDocument' or 'GoodDocumentWriter'.
public mustinherit class DocumentWriter
public property Doc as Document
public sub new()...
end class
public class GoodDocumentWriter
inherits DocumentWriter
public sub new
mybase.Doc = new GoodDocument
end sub
end class
public class BadDocumentWriter
inherits DocumentWriter
public sub new
mybase.Doc = new BadDocument
end sub
end class
Question:
Is there a design pattern that allows for derived classes to have members that don't exist at the base class level?
Do all properties have to live at the base class level?
Revised
I was trying to be brief with my initial question and I made the mistake of over simplifying the situation. In short, I did realize that it should be possible to have different properties on each of the derived classes. (I typed that in a tongue-in-cheek manor and didn't mean to keep it in the final post).
I realize now that the problem that I was experiencing was really symptomatic of a larger issue which needed addressing.
It appears that I was encountering compiler complaints that could be corrected by further refactoring and looser coupling. While others answered the basic question that I posed, Ryan Gross' example really helped kick start some new ideas.
Thanks!
What you should do in this case is define the operations that can be performed on instances of Document in an interface. In your case maybe there is a WriteThings operation, so you would have:
public interface Writeable {
public sub WriteThings();
}
Then in your derived classes you would implement the method to utilize the internal data of the class. For example:
public mustinherit class Document implements Writeable
public property Contents as string
public sub new()...
public sub WriteThings();
end class
public class GoodDocument
inherits Document
public property GoodThings as string
public sub new()...
public sub WriteThings()
//Do something with GoodThings
end sub
end class
public class BadDocument
inherits Document
public property BadThings as string
public sub WriteThings()
//Do something with BadThings
end sub
public sub new()...
end class
Finally, client code that needs to call WriteThings accesses it through an interface:
public mustinherit class DocumentWriter
public property Doc as Writable
public sub new()...
public sub PerformWrite()
Doc.WriteThings();
end sub
end class
It is generally not a good idea to build several parallel class hierarchies. In this case, one DocumentWriter class should be able to write any class that implements Writeable by invoking its WriteThings method.
If all the properties live at the base class level, then I'm not sure what the point of a derived class would be. :) You'd be able to do everything with the base class.
So, yes. If something is applicable only to GoodDocument and not to Document, then it should be in GoodDocument.
To answer your question specifically:
Yes, you just create multiple layers in the inheritance hierarchy: You have a base class, and then many two “branches” (good and bad, to use your terminology). Any properties that are only relevant to either branch, you declare in the class that inherits from the base class. Those properties will only be visible to that class and any classes inheriting from it.
No, properties can be declared anywhere within your inheritance hierarchy.
I'm trying to force an inherited class to use a custom attribute. I'm creating a class library where the user who wants to create an item will do so, but be forced to add an attribute (or visual studio will automatically add the default attribute) to their inherited class. Here is what I'm hoping to achieve:
BaseClass.vb:
<CustomAttribute(10)> _
Public Class BaseClass
End Class
MyClass.vb:
<CustomAttribute(12)> _
Public Class MyClass
Inherits BaseClass
Public Sub New()
Mybase.New()
End Sub
End Class
So the thought is that much like when you mark a function as "MustOverride" and then the inherited class must override the function, I want the attribute to be "MustOverride" causing the inherited class to specify the value.
I've tried this, and it will work, but it would be much cleaner if I could use attributes:
BaseClass.vb:
Public MustInherit Class BaseClass
Public MustOverride ReadOnly Property CustomAttribute() As String
End Class
MyClass.vb:
Public Class MyClass
Inherits BaseClass
Public Sub New()
Mybase.New()
End Sub
Public Overrides ReadOnly Property CustomAttribute() As String
Get
Return "testing"
End Get
End Property
End Class
Thank you for any help you can provide.
Scott
Did you consider implementing an interface instead? I assume that you're using a base class as you want to provide some code in the base, if not then an Interface might be better depending on your other requirements:
Interface IBase
ReadOnly Property CustomAttribute() As String
End Interface
It's still very compact and when you type 'Implements IBase' in a new class Visual Studio will fill in the code for you.
There's no way in .NET to force a class to define an attribute at compile time. The best you'll be able to do is check at run-time whether the attribute was defined, and if not to throw an exception.