I'm writing some code in VB.Net which I hope demonstrate to colleagues (not to say familiarise myself a little more) with various design patterns - and I'm having an issue with the FactoryMethod Pattern.
Here's my code:
Namespace Patterns.Creational.FactoryMethod
''' <summary>
''' This is the Factory bit - the other classes are merely by way of an example...
''' </summary>
Public Class CarFactory
''' <summary>
''' CreateCar could have been declared as Shared (in other words,a Class method) - it doesn't really matter.
''' Don't worry too much about the contents of the CreateCar method - the point is that it decides which type
''' of car should be created, and then returns a new instance of that specific subclass of Car.
''' </summary>
Public Function CreateCar() As Car
Dim blnMondeoCondition As Boolean = False
Dim blnFocusCondition As Boolean = False
Dim blnFiestaCondition As Boolean = False
If blnMondeoCondition Then
Return New Mondeo()
ElseIf blnFocusCondition Then
Return New Focus()
ElseIf blnFiestaCondition Then
Return New Fiesta()
Else
Throw New ApplicationException("Unable to create a car...")
End If
End Function
End Class
Public MustInherit Class Car
Public MustOverride ReadOnly Property Price() As Decimal
End Class
Public Class Mondeo Inherits Car
Public ReadOnly Overrides Property Price() As Decimal
Get
Return 17000
End Get
End Property
End Class
Public Class Focus Inherits Car
Public ReadOnly Overrides Property Price() As Decimal
Get
Return 14000
End Get
End Property
End Class
Public Class Fiesta Inherits Car
Public ReadOnly Overrides Property Price() As Decimal
Get
Return 12000
End Get
End Property
End Class
End Namespace
When I try to compile this, I am getting errors (BC30311) in the CarFactory.CreateCar telling me that it can't convert Fiesta, Mondeo, and Focus into Car. I don't see what the issue is - they're all subclasses of Car.
Doubtless I'm overlooking something simple. Can anyone spot it?
Cheers,
Martin.
Put Inherits on new line or use : to separate the class name and Inherits statement:
Public Class Mondeo
Inherits Car
...
Public Class Focus
Inherits Car
...
Public Class Fiesta
Inherits Car
...
Your Inherits keyword must be on a new line. This is documented by Microsoft on their help and Support. http://support.microsoft.com/kb/307222
Change the SavingsAccount class
definition as follows, so that
SavingsAccount inherits from Account
(note that the Inherits keyword must
appear on a new line):
The first error in the list is just the one at the lowest line number, it's not always the actual cause of the error.
Further down in the list of errors you will see (among several others) three more errors saying End of statement expected. at each of the subclasses. This is beacuse Class and Inherits are separate statements and go on separate lines:
Public Class Mondeo
Inherits Car
or:
Public Class Mondeo : Inherits Car
When you fix these errors, the classes do actually inherit from Car, and your code works.
Related
So to start this off; I'm a beginner in VisualBasic.Net and my classes require me to learn it. The current subject is object constructors and constructor methods. The current exercise (it's not graded or an exam) is requiring us to make a parent class with a constructor method, and a child class with a new() that calls said function. It looks a bit like this;
Protected MustInherit Class Vehicle()
Protected ReadOnly Property Serial_No As Integer
Protected Property Mileage As Integer
Protected Property Color As String
Protected Function CreateVehicle() As Object
End Function
End Class
Public Class Car
Inherits Vehicle
Public ReadOnly Property Car_Type As String
Public Sub New()
End Sub
End Class
The thing I'm having issues with is that I'm not sure how to go about it? Can't ReadOnly properties ONLY be edited in the constructor itself, and doesn't the object need to be initialized in the constructor? Is there something particular I need to add in the CreateVehicle function?
I did ask the teacher but his answer was 'just give up on it and go do something else', which is ultimately pretty unhelpful.
Edit: (added the inheritance to the child class)
So, after being asked for clarification on what I'm trying to do; the exercise itself is not entirely about doing this, but it is the thing in the exercise that I'm struggling with. The goal is to create a Car object utilizing the constructor (New()), but the constructor must call a secondary function located inside the parent class, Vehicle.
My issue is the following : I'm not sure how to go about implementing the function inside the constructor. I know how to call methods/subs/functions and how to get returns from them, but I'm not sure on how I would go about returning a ReadOnly property's values from a secondary function. Don't readonly properties become uneditable outside of the constructor?
I could always return each value separately instead of as an object, and then set the Car object's values to be equal to the return of the function, individually. But then what's the point of calling a separate function instead of just passing everything as a parameter and doing it directly in the constructor?
This is probably what your teacher is looking for:
Public MustInherit Class Vehicle
Protected ReadOnly Property Serial_No As Integer
Protected Sub New(serialNumber As Integer)
Me.Serial_No = serialNumber
End Sub
End Class
Public Class Car
Inherits Vehicle
Public ReadOnly Property Car_Type As String
Public Sub New(serialNumber As Integer, carType As String)
MyBase.New(serialNumber)
Me.Car_Type = carType
End Sub
End Class
Both constructors take in parameters so the ReadOnly properties can be set.
Consider the following classes representing an Ordering system:
Public Class OrderBase
Public MustOverride Property OrderItem as OrderItemBase
End Class
Public Class OrderItemBase
End Class
Now, suppose we want to extend these classes to a more specific set of order classes, keeping the aggregate nature of OrderBase:
Public Class WebOrder
Inherits OrderBase
Public Overrides Property OrderItem as WebOrderItem
End Property
End Class
Public Class WebOrderItem
Inherits OrderItemBase
End Class
The Overriden property in the WebOrder class will cause an error stating that the return type is different from that defined in OrderBase... however, the return type is a subclass of the type defined in OrderBase. Why won't VB allow this?
You can't do that - it's changing the signature defined on the base. To do what you are trying to do you need to use generics:
Public Class OrderBase(Of T As IOrderItem)
Public ReadOnly Property OrderItems As IList(Of T)
End Class
My Visual Basic is rusty so hopefully that is accurate...
You cannot change the signature of your class upon overriding it. You can, however, return a derived type:
Public Overrides Property OrderItem() as OrderItemBase
Get
Return New WebOrderItem()
End Get
End Property
Public Sub Whatever()
Dim item As WebOrderItem = DirectCast(OrderItem, WebOrderItem)
End Sub
Alternatively, if you want to enforce the types more strictly, use generics with generic type constraints, as shown below:
Public MustInherit Class OrderBase(Of T As OrderItemBase)
Public MustOverride ReadOnly Property OrderItem() As T
End Class
Public Class OrderItemBase
End Class
Public Class WebOrder(Of T As WebOrderItem)
Inherits OrderBase(Of T)
Public Overrides ReadOnly Property OrderItem() As T
Get
Return New WebOrderItem()
End Get
End Property
End Class
Public Class WebOrderItem
Inherits OrderItemBase
End Class
Or do this if you don't want WebOrder to be a generic class as well:
Public Class WebOrder
Inherits OrderBase(Of WebOrderItem)
Public Overrides ReadOnly Property OrderItem() As WebOrderItem
Get
Return New WebOrderItem()
End Get
End Property
End Class
One approach is to have a protected overridable method, and then have a public non-overridable method which calls the overridable one. Any time the return value for the function in the derived class should change, have a notoverridable override of the overridable method call a new overridable method which returns the more refined type, and also shadow the earlier version of the public function with one that uses the new override. If vb.net allowed one class to both override and shadow the same member, things would be much cleaner, but there's no way to do that.
Public Class CarFactory
Protected Overridable Function DerivedMakeCar() as Car
' make a car
End Function
Public Function MakeCar() as Car
Return DerivedMakeCar()
End Function
End Class
Public Class FordFactory
Inherits CarFactory
Protected Overrides Function DerivedMakeCar() As Car
Return DerivedMakeFord()
End Function
Protected Overridable Function DerivedMakeFord() As Ford
' Make a Ford
End Function
Public Shadows Function MakeCar() As Ford
Return DerivedMakeFord()
End Function
End Class
A simpler alternative in some cases may be to have a public overridable MakeCar() function which always returns an object of type Car, but have a FordFactory also include a MakeFord() function which returns a Ford.
The overridden MakeCar() function would be NotOverridable and would simply call MakeFord. In some ways, the latter approach can be cleaner, but if there's a common naming convention (e.g. factories have a MakeProduct method which returns the most derived type) it may be useful to use Shadows.
Disclaimer: I am fairly new to working with generics so I am not entirely sure if what I am trying to do even makes sense or is possible.
I have a bunch of user controls in a project. All of these user controls share a similar property so I want to move it into a base class. The only difference is the return type of the property.
I have three classes interacting in this scenario. The first class is a base type, which inherits from CompositeControl and will be inherited by other classes in my project:
Friend Class MyBaseClass(Of T As {New})
Inherits CompositeControl
Private _someProperty As T = Nothing
Protected ReadOnly Property SomeProperty As T
Get
// dumbed down for the sake of example
If _someProperty Is Nothing Then
_someProperty = New T()
End If
Return _someProperty
End Get
End Property
End Class
Then I have this control class, which inherits from MyBaseClass:
Public Class MyControlClass
Inherits MyBaseClass(Of MyReturnTypeClass)
// snip...
End Class
And finally MyReturnTypeClass which is what the base's SomeProperty should return:
Friend Class MyReturnTypeClass
Public Property AutoProperty1 As Boolean = False
Public Property AutoProperty2 As String = String.Empty
// etc
End Class
When I attempt to build the project, I get this error from MyControlClass:
Inconsistent accessibility: type argument 'MyReturnTypeClass' is less accessible than Class 'MyControlClass'.
I need MyControlClass to be Public so it can be consumed by other projects, and I also want the MyBaseClass and MyReturnTypeClass to be Friend so they cannot be seen/used by consumers. Am I just missing some special keyword somewhere or is this not possible?
You cannot inherit from a base class that is less accessible than the derived class. So for instance, this won't work:
Friend Class MyBase
End Class
Public Class MyDerived
Inherits MyBase ' Won't compile because MyBase is less accessible
End Class
Therefore, since in your example, MyBaseClass(T) has is a friend type, but you are trying to inherit from it into a public MyControlClass type. Therefore, even if you took generics and MyReturnTypeClass out of the "equation", it still wouldn't work.
However, with generics, even if no member of the public interface of the class actually uses the generic type, the type must still be at least as accessible as the derived type. For instance:
Public Class MyBase(Of T)
' T not actually used at all
End Class
Friend Class MyOtherType
End Class
Public Class MyDerived
Inherits MyBase(MyOtherType) ' Won't compile because MyOtherType is less accessible
End Class
The base class must be at least as accessible as the derived class. This is a language restriction (see here).
If you intend to avoid MyBaseClass being instantiated by consumers, consider marking it Public MustInherit instead of Friend. Hope this helps.
Shell example is below. Basically, I want a client and employee to implement the SSN property from IPerson. However, I want client to have get and set (which isn't an issue), but I want employee to have get only.
Public Interface IPerson
Property SSN As String
End Interface
Public Class Client
Implements IPerson
Public Property SSN As String Implements AELName.IPerson.SSN
Get
Return _SSN
End Get
Set(value As String)
_SSN = value
End Set
End Property
End Class
Public Class Employee
Implements IPerson
Public Readonly Property SSN As String Implements AELName.IPerson.SSN
Get
Return _SSN
End Get
End Property
End Class
Employee generates an error of "'SSN' cannot implement 'SSN' because there is not matching property on interface 'IPerson'". Is there a somewhat simple way to override the SSN implementation for Employee?
You can implement an empty Set - one that doesn't update anything.
Public Class Employee
Implements IPerson
Public Readonly Property SSN As String Implements AELName.IPerson.SSN
Get
Return _SSN
End Get
Set
' Make read only for Employee
End Set
End Property
End Class
I would suggest splitting the interface into IReadablePerson and IReadWritePerson, with the latter inheriting the former. Note that the former interface is not IImmutablePerson, since the latter name would imply to consumers of the class that they should not expect any of its properties ever to change; an object which implements IReadWritePerson would not abide such expectation, but would abide the expectation that the person should be readable.
One slight annoyance with splitting the interface is that it will be necessary for the IReadWritePerson to include the modifier Shadows in the declarations of its read/write properties, and implementers of IReadWritePerson will have to provide both a read-only implementation of IReadablePerson and a read-write implementation of IReadWritePerson. In C#, a public implementation of a read-write property can automatically generate implementations for any like-named read-only, write-only, or read-write properties which are part of any interfaces the class implements, but when explicitly declaring which interface is being implemented, the style of the interface (read-only, write-only, read-write) must precisely match that of the implementation. Annoying.
The annoyance is made worse by the fact that one cannot simply declare IReadableFoo with a read-only property, IWriteOnlyFoo with a write-only property, and have IReadWriteFoo simply inherit both. If an interface implements a read-only property and a write-only property with the same name, neither property will be usable because the compiler will announce that in statements like somevariable = object.someProperty or someObject.someProperty = someVariable, it's "ambiguous" which implementation to use. Not that I can see any ambiguity--I can't see how the first could use anything but a getter, or the latter anything but a setter, but the compiler can't resolve it.
To answer your title question "Can I override an interface property" ... Absolutely. Here's an example of how to do so. You simply add the Overridable keyword to your base concrete implementation. I know that doesn't solve changing the property to ReadOnly, but I figured I'd point out that overriding a base classes concrete implementation of an interface is possible.
Module Module1
Sub Main()
Dim iEntity As IEntity = New MyEntity
iEntity.SetMessage(iEntity)
Console.WriteLine(iEntity.Message)
Console.ReadKey()
End Sub
End Module
Public Interface IEntity
Property Message As String
Sub SetMessage(entity As IEntity)
End Interface
Public Class MyEntity
Inherits BaseEntity
Public Overrides Property Message As String
Get
Return String.Format("{0}.. and overroad.", MyBase.Message)
End Get
Set(value As String)
MyBase.Message = value
End Set
End Property
Public Overrides Sub SetMessage(entity As IEntity)
Me.Message = "I was set from MyEntity."
End Sub
End Class
Public Class BaseEntity
Implements IEntity
Public Overridable Property Message As String Implements IEntity.Message
Public Overridable Sub SetMessage(entity As IEntity) Implements IEntity.SetMessage
Me.Message = "I was set from BaseEntity."
End Sub
End Class
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.