I'd like to have a Private or Protected "Setter" for a property that also happens to be an abstract (MustOverride). I'm porting some code from C# to VB and in C# this is pretty straight forward. In VB not so much (for me anyway).
Some code...
In C#...
public abstract class BaseClassWithAnAbstractProperty
{
public abstract int AnAbstractIntegerProperty { get; protected set; }
}
public class Foo : BaseClassWithAnAbstractProperty
{
private int _anAbstractIntegerPropertyField = 0;
public override int AnAbstractIntegerProperty
{
get { return _anAbstractIntegerPropertyField; }
protected set { _anAbstractIntegerPropertyField = value; }
}
}
In VB...
Public MustInherit Class BaseClassWithAnAbstractProperty
Public MustOverride Property AnAbstractIntegerProperty() As Integer
End Class
Public Class Foo
Inherits BaseClassWithAnAbstractProperty
Private _anAbstractIntegerPropertyField As Integer
Public Overrides Property AnAbstractIntegerProperty As Integer
Get
Return _anAbstractIntegerPropertyField
End Get
Protected Set(ByVal value As Integer)
_anAbstractIntegerPropertyField = value
End Set
End Property
End Class
The issue seems to be the inability to flesh-out the Get/Set specifics in the declaration.
Am I chasing a ghost?
For the record, the closest VB translation would give you:
Public MustInherit Class BaseClassWithAnAbstractProperty
Public ReadOnly MustOverride Property AnAbstractIntegerProperty() As Integer
End Class
This might work, but as I found out, VB doesn't support this for Interfaces, at least
Related
I am struggling with an extension method in VB.NET, but I can't find why I can't implement this (I came from C# and I still having issues like this between language specification and how the language works, sorry if this question is too newbie):
namespace FakeBusiness.BusinessInterface
{
public interface IBusiness
{
int Id { get; set; }
string Name { get; set; }
}
}
namespace FakeBusiness.SharedExtensions
{
using FakeBusiness.BusinessInterface;
public static class ExtensionsMethods
{
public static bool IsEmpty(this IBusiness theObject)
{
return theObject != null && theObject.Id != 0;
}
}
}
namespace FakeBusiness.BusinessLogic
{
using FakeBusiness.BusinessInterface;
using FakeBusiness.SharedExtensions;
public class Business : IBusiness
{
public int Id { get; set; }
public String Name { get; set; }
}
public static class Program
{
public static void Main(string[] args)
{
IBusiness obj = new Business();
Console.WriteLine($"The object is: {(obj.IsEmpty() ? "empty" : "not empty")}");
}
}
}
And I want to achieve the same logic but for a reason VB.NET says 'Cannot resolve the symbol' even if I import explicitly the namespace from the extension method:
Namespace FakeBusiness.SharedExtensions {
<Extension()>
Public Function IsBusinessObjectEmtpy(ByVal business As IBusiness) As Boolean
Return (business IsNot Nothing AndAlso business.Id = 0)
End Function
End Namespace
Namespace FakeBusiness.BusinessLogic
Public Class BusinessObject : Implements IBusiness
Property Id As Integer Implements IBusiness.Id
Property Name As String Implements IBusiness.Name
Public Sub New()
End Sub
End Class
Public Interface IBusiness
Property Id As Integer
Property Name As String
End Interface
Public Class FakeBusiness.SomeLogic
Public Sub SomeLogic()
Dim newObject = New BusinessObject()
If newObject.IsBusinessObjectEmpty() Then
' Do something...
End If
End Sub
End Class
End Namespace
Also I read that a possible solution is to use the instructions Option Strict On/Off and also Option Infer On/Off.
I tried every possible combination between these pair of compiler instructions but it didn't work.
Anyone knows how to fix this issue with an extension method?
Another possible solution is to put the same method into a base class and implement with an interface, but I want to achieve this in this way
because it will be useful to use in every class if I use a TypeParameter in the extension method.
Any suggestion?
In a Console Application project with a root namespace of FakeBusiness, the following is the direct equivalent of that C# code:
Namespace BusinessInterface
Public Interface IBusiness
Property Id As Integer
Property Name As String
End Interface
End Namespace
Imports System.Runtime.CompilerServices
Imports FakeBusiness.BusinessInterface
Namespace SharedExtensions
Public Module ExtensionMethods
<Extension>
Public Function IsEmpty(theObject As IBusiness) As Boolean
Return theObject IsNot Nothing AndAlso theObject.Id <> 0
End Function
End Module
End Namespace
Imports FakeBusiness.BusinessInterface
Imports FakeBusiness.SharedExtensions
Namespace BusinessLogic
Public Class Business
Implements IBusiness
Public Property Id As Integer Implements IBusiness.Id
Public Property Name As String Implements IBusiness.Name
End Class
Module Program
Sub Main(args As String())
Dim obj As IBusiness = New Business()
Console.WriteLine($"The object is: {If(obj.IsEmpty(), "empty", "Not empty")}")
End Sub
End Module
End Namespace
I have two classes, one inheriting from the other. The first shows a summary view of data (4+ columns) and the child shows a detail view (40+ columns). Both classes are accessing the same table and share the same columns being accessed.
Can my child class inherit from the parent class so I only have to change mappings in one place? I'd rather not have duplicate code running rampant.
E.g.:
Public Class Parent
Public Overridable Property MyProp As String
Public Overridable Property MyProp2 As String
End Class
Public Class Child : Inherits Parent
Public Overridable Property MyProp3 As String
End Class
I want to do something like this:
Public Class ParentMapping
Inherits ClassMapping(Of Parent)
Public Sub New()
Me.Property(Function(x) x.MyProp, Sub(y) y.column("MyProp"))
Me.Property(Function(x) x.MyProp2, Sub(y) y.column("MyProp2"))
End Sub
End Class
Public Class ChildMapping
Inherits SubClassMapping(of Child)
Public Sub New()
' I want to be able to inherit the mappings of the parent here.
MyBase.New()
Me.Property(Function(x) x.MyProp3, Sub(y) y.column("MyProp3"))
End Sub
End Class
If you want the Child to be a subclass of parent in db also, you'll need a discriminator column.
If you just want to reuse code then share a mapping base class
public abstract class ParentChildMapping<T> : ClassMapping<T> where T : Parent
{
public ParentChildMapping()
{
// map shared properties here
}
}
public class ParentMapping : ParentChildMapping<Parent>
{
}
public class ChildMapping : ParentChildMapping<Child>
{
public ChildMapping()
{
// map additional properties here
}
}
How do I make the properties of a class available in an inheriting class, for a variable that is declared to be the type of one of the interfaces implemented by that class?
What I have done so far is to create an abstract class MyAbstract with the keyword MustInherit and in the inheriting class MyInheritingClass I have added inherits and then the name of the abstract class. Now this is all fine, but in my inheriting class, if I create an interface on that class MyInterface and use that interface elsewhere in my code, I have then found that I cannot see the properties from my abstract class, on the variable declared with that interface.
Am I doing something wrong here, or is there something else that I need to do?
An example would be as follows:
Public MustInherit Class MyAbstract
Private _myString as String
Public Property CommonString as String
Get
Return _myString
End Get
Set (value as String)
_myString = value
End Set
End Property
End Class
Public Class MyInheritingClass
Inherits MyAbstract
Implements MyInterface
Sub MySub(myParameter As MyInterface)
myParameter.CommonString = "abc" ' compiler error - CommonString is not a member of MyInterface.
End Sub
'Other properties and methods go here!'
End Class
So, this is what I am doing, but when I use MyInterface, I cannot see the properties of my Abstract Class!
Unless I've completely misunderstood your question, I'm not sure why you are confused by this behavior. Not only is that how it should work, but that is also how it works in c#. For instance:
class Program
{
private abstract class MyAbstract
{
private string _myString;
public string CommonString
{
get { return _myString; }
set { _myString = value; }
}
}
private interface MyInterface
{
string UncommonString { get; set; }
}
private class MyInheritedClass : MyAbstract, MyInterface
{
private string _uncommonString;
public string UncommonString
{
get { return _uncommonString; }
set { _uncommonString = value; }
}
}
static void Main(string[] args)
{
MyInterface test = new MyInheritedClass();
string compile = test.UncommonString;
string doesntCompile = test.CommonString; // This line fails to compile
}
}
When you access an object through any interface or base class, you will only ever have access to the members that are exposed by that interface or base class. If you need to access a member of MyAbstract, you need to cast the object as either MyAbstract or MyInheritedClass. This is true in both languages.
I'm getting this error when trying to implement an interface in vb.net:
Public Interface IFoo
ReadOnly Property Foo() As String
End Interface
Public Class myFoo
Implements IFoo
Public ReadOnly Property Foo() As String
Get
return "Foo"
End Get
End Property
...
End Class
What is missing?
You will want to tell the code that the myFoo.Foo implements the IFoo.Foo (notice the added Implements IFoo.Foo):
Public Interface IFoo
ReadOnly Property Foo() As String
End Interface
Public Class myFoo
Implements IFoo
Public ReadOnly Property Foo() As String Implements IFoo.Foo
Get
Return "Foo"
End Get
End Property
End Class
As far as I know, VB.NET does not support implicit interface implementations in the same way as C# does.
In c# you can have
public class Foo
{
public Foo(string name)
{
//do something
}
public Foo(string name, int bar) : this(name)
{
//do something
}
}
Is there a VB.Net equivalent?
It looks similar to Java in this respect:
Public Class Foo
Public Sub New(name As String)
' Do something '
End Sub
Public Sub New(name As String, bar As Integer)
Me.New(name)
' Do something '
End Sub
End Class
Note that you have to use MyBase.New(...) in case you want to call a constructor of a base class. See also VB.NET OOP Part2 – Understanding Constructors.