One table many classes - vb.net

Say I have a database structure like this:
create table Product(id int not null identity,Name varchar(30))
INSERT INTO Product VALUES ('ProductA')
INSERT INTO Product VALUES ('ProductB')
and a class structure like this:
Imports System.Data.SqlClient
Public Class Product
Protected ProductName As String
Public Overridable Sub Display()
End Sub
End Class
Public Class ProductA
Inherits Product
Public Sub New(ByVal product As String)
ProductName = product
End Sub
Public Overrides Sub Display()
'Specific logic to display product A
End Sub
End Class
Public Class ProductB
Inherits Product
Public Sub New(ByVal product As String)
ProductName = product
End Sub
Public Overrides Sub Display()
'Specific logic to display product B
End Sub
End Class
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim p1 As Product
Dim p2 As Product
p1 = New ProductA("ProductA")
p2 = New ProductB("ProductB")
p1.Display()
p2.Display()
End Sub
End Class
There is a Property (Product) that identifies, which product the class relates to. This does not look correct to me. Is there a better way of modelling it? This is similar to the NHibernate concept of a Discriminator (I am not using NHibernate in this case).

With you latest change, you should move your constructor to the base class. Aside from that, the design is fine.
Public Class Product
Protected ProductName As String
Public Sub New(ByVal product As String)
ProductName = product
End Sub
Public Overridable Sub Display()
End Sub
End Class
Public Class ProductA
Inherits Product
Public Overrides Sub Display()
'Specific logic to display product A
End Sub
End Class
Also, in your declarations you can use the inherited class:
Dim p1 As ProductA
Dim p2 As ProductB

Related

how to dont call contruvtor Inherits in vb

I want to call Dim objFkkiNinteiJokyoRpt As New A(objCsv) in class C. But class A Inherits Common. If now call contructor will An error occurred.Because type Object C.CsvGenerator diference type Object in common. I thnk now stop call to contructor common (or any other way) but i dont know how to do. Helf me please. Sorry because my english so bad
Public Class A Inherits Common
Public _objCsv As C.CsvGenerator
Friend Sub New(ByVal objCsv As C.CsvGenerator)
_objCsv = objCsvGenerator
End Sub
Public Sub New()
End Sub
End Sub
Public Sub New(ByVal objRSReportObj As Object)
MyBase.New(objRSReportObj)
InitializeReport()
End Sub
End Class
Public Class C
Private Function SelectCSV
Dim objCsv As New CsvGenerator("")
Dim objFkkiNinteiJokyoRpt As New A(objCsv)
End Function
Friend Class CsvGenerator
Inherits cmShare.cmObject
End Class
End Class
Public Class Common
Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal objRSReport As Object)
MyBase.New(objRSReport)
End Sub
End Class

Call derrived class constructor without arguments from main class constructor with arguments

I have a abstract base class and a derrived class. The base class has some members that I want to set based on the derrived class type. But I also have a common constructor for all derrived classes that accept an argument. That common constructor with an argument is repeating code I would like to get rid of.
Public MustInherit Class B
Protected member1 As String
Protected member2 As String
End Class
Public Class D1 : Inherits B
Public Sub New()
Me.member1 = "D1" ' individual code here
End Sub
Public Sub New(arg As String)
Me.New()
Me.meber2 = arg ' repeating code here, should be moved to base class
End Sub
End Class
Public Class D2 : Inherits B
Public Sub New()
Me.member1 = "D2" ' individual code here
End Sub
Public Sub New(arg As String)
Me.New()
Me.meber2 = arg ' repeating code here, should be moved to base class
End Sub
End Class
How can I refactor this, so that the derrived constructor without arguments is called, even when invoking the constructor with the argument in the base class?
Your code wouldn't even compile since the member are Private. You could have a Protected method that populates the member.
Public MustInherit Class B
Private member1 As String
Private member2 As String
Protected Sub SetMembers(ByVal m1 As String, ByVal m2 As String)
member1 = m1
member2 = m2
End Sub
End Class
Public Class D1 : Inherits B
Public Sub New()
Me.New("")
End Sub
Public Sub New(arg As String)
SetMembers("D1", arg)
End Sub
End Class
Public Class D2 : Inherits B
Public Sub New()
Me.New("")
End Sub
Public Sub New(arg As String)
SetMembers("D2", arg)
End Sub
End Class
You could change SetMembers to a protected New and call it with MyBase.New(..., ...) if you want.
Why not add a constructor to the base class?
Public MustInherit Class B
Public Sub New(arg As String)
Me.member2 = arg
End Sub
Protected member1 As String
Protected member2 As String
End Class
Public Class D1 : Inherits B
Public Sub New(arg As String)
MyBase.New(arg)
Me.member1 = "D1"
End Sub
End Class
Public Class D2 : Inherits B
Public Sub New(arg As String)
MyBase.New(arg)
Me.member1 = "D2"
End Sub
End Class
It doesn't really reduce the duplication, per se, since each derived class still has the line that calls the base constructor, passing it the value, but it does allow you to centrally maintain what it does with that value, and it does force all derived classes to do it. That way you can never create a derived class where you forget to provide that value.
In fact, if you want to require all derived classes to provide a default value for member1, then you could add that as a parameter to the base constructor as well:
Public MustInherit Class B
Public Sub New(member1 As String, member2 As String)
Me.member1 = member1
Me.member2 = member2
End Sub
Private member1 As String
Private member2 As String
End Class
Public Class D1 : Inherits B
Public Sub New(arg As String)
MyBase.New("D1", arg)
End Sub
End Class
Public Class D2 : Inherits B
Public Sub New(arg As String)
MyBase.New("D2", arg)
End Sub
End Class

How to select which object to instantiate without Select Case?

Say I have three classes. A base class Person and two other classes (Employee and Manager) each inherits from Person.
Public Class Person
Public Property Name As String
Public Overridable ReadOnly Property Salary As Decimal
Get
Return 0
End Get
End Property
Public Sub New()
End Sub
End Class
Class Employee:
Public Class Employee
Inherits Person
Overrides ReadOnly Property Salary As Decimal
Get
Return 100
End Get
End Property
Sub New()
MyBase.New()
End Sub
End Class
Class Manager:
Public Class Manager
Inherits Person
Overrides ReadOnly Property Salary As Decimal
Get
Return 1000
End Get
End Property
Sub New()
MyBase.New()
End Sub
End Class
My problem is how to create a new Person(based on a ListBox) that can be either Person/Employeeor Manager and retrieve the Salary Property without going through Select Case or If-else in the ListBox1_SelectedIndexChanged event. To do this selection, I have added another class, named Identify, that takes the selected index of the Listbox and pass it to getProsonType method and return the selected category. Please look at my code below.
The form1 code looks like:
Public Class Form1
Private P As Identify
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles
MyBase.Load
ListBox1.Items.Add("Person")
ListBox1.Items.Add("Employee")
ListBox1.Items.Add("Manager")
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As
EventArgs) Handles ListBox1.SelectedIndexChanged
P = New Identify(CType(ListBox1.SelectedIndex, PersonType))
Dim PGeneral As Person
PGeneral = P.GeneralPerson
Label1.Text = PGeneral.Salary
End Sub
End Class
I have assigned the three types to a public Enum PersonType just to restrict the selection.
Public Enum PersonType
Person = 0
Employee = 1
Manager = 2
End Enum
The Identity Class looks like:
Public Class Identify
Public Property PType As PersonType
Public ReadOnly Property GeneralPerson As Person
Get
Return getProsonType(PType)
End Get
End Property
Private Function getProsonType(ByVal SomeOne As PersonType) As Person
Dim pp As Person
Select Case SomeOne
Case PersonType.Person
pp = New Person()
Case PersonType.Employee
pp = New Employee()
Case PersonType.Manager
pp = New Manager()
End Select
Return GeneralPerson
End Function
Sub New(ByVal PersonType As PersonType)
Me.PType = PersonType
End Sub
End Class
After running the project I get the error System.StackOverflowException. I am not sure if this is the cleanest or the correct way to do this and I looked in many places and reached this dead end!
Please help me to correct this or find a better way.
Thanks in advance.

Hiding function on nested class

Public Class Class1
Private names As List(Of String)
Private _class2 As New Class2
Public Sub AddName(ByVal name As String)
names.Add(name)
_class2.Add()
End Sub
Public ReadOnly Property AddAge(ByVal name As String) As Class2
Get
_class2.index = names.IndexOf(name)
Return _class2
End Get
End Property
Public Sub Clear()
names.Clear()
_class2.Clear()
End Sub
Public Class Class2
Private _age As List(Of Integer)
Protected Friend index As Integer
Public Property Age() As Integer
Get
Return _age(index)
End Get
Set(ByVal value As Integer)
_age(index) = value
End Set
End Property
Public Sub Add()
_age.Add(0)
End Sub
Public Sub Clear()
_age.Clear()
End Sub
End Class
End Class
How can I hide ,Sub Clear and Sub Add on class2, so they'll only be visible on class1, like;
Public Sub Clear()
names.Clear()
_class2.Clear() '<<<<<<<
End Sub
I want they do not be visible on Sub Main(), like they are below.
Sub Main()
Dim person As New Class1
person.AddAge("kid").Clear() '<<<<<<
person.AddAge("kid").Add() '<<<<<<
End Sub
If I put Protected, I class1 cannot access it. If I put Protected Friend, Sub Main() can still access them. Thanks for your help and time.
Used -Hans Passant- comment.
"Trust in .NET follows assembly boundaries. If you get two classes in one assembly then there are two programmers that know how to find each other if there's a problem. The only way to get what you want is to put these classes in a separate class library project. Which then lets you use Friend. And whomever writes that Main method doesn't have to be friendly."

Organizing VB.Net Mehods

Say I have a class with several methods within it. I want to organize the methods into groupings that can be accessed without constructing a new object each time. The purpose is to group the methods of the class into logical buckets
For instance:
Dim myclass as MyCustomClass
myclass.Shipping.Get_List()
myclass.Production.Get_List()
What is the best way to do this? I tried nested classes, but VB.NET won't let me access the methods as shown above.
so this is how i would do what you want
this is not the best design of the world but it would work
I would suggest you to move the actual get_list and other kind of method / property into the specific class while keeping the common one in the parent class, which in this case is test
but then, I have no idea what your code look like so from that point on, it's your choice
Module Module1
Sub Main()
Dim test As New test
test.Production.Get_List()
test.Shipping.Get_List()
End Sub
End Module
Public Class Shipping
Private parent As test
Public Sub New(ByRef parent As test)
Me.parent = parent
End Sub
Public Function Get_List() As List(Of Integer)
Return parent.GetShipping_List
End Function
End Class
Public Class Production
Private parent As test
Public Sub New(ByRef parent As test)
Me.parent = parent
End Sub
Public Function Get_List() As List(Of Integer)
Return parent.GetProduction_List
End Function
End Class
Public Class test
Public Property Production As Production
Public Property Shipping As Shipping
Public Function GetShipping_List() As List(Of Integer)
Return Nothing
End Function
Public Function GetProduction_List() As List(Of Integer)
Return Nothing
End Function
Public Sub New()
Production = New Production(Me)
Shipping = New Shipping(Me)
End Sub
End Class
With caution that you more than likely should re-evaluate your architecture, you could implement your pattern like this:
Public Class MyCustomClass
Private _shippingList As List(Of String)
Private _productionList As List(Of String)
Public Production As ProductionClass
Public Shipping As ShippingClass
Public Sub New()
Production = New ProductionClass(Me)
Shipping = New ShippingClass(Me)
End Sub
Public Class ShippingClass
Private _owner As MyCustomClass
Public Sub New(owner As MyCustomClass)
_owner = owner
End Sub
Public Function Get_List()
Return _owner._productionList
End Function
End Class
Public Class ProductionClass
Private _owner As MyCustomClass
Public Sub New(owner As MyCustomClass)
_owner = owner
End Sub
Public Function Get_List()
Return _owner._productionList
End Function
End Class
End Class
However, if your true intent is simply organizing the methods in a more accessible and logical manner, I would suggest considering:
Public Class MyCustomClass
Public Sub ShippingListGet()
End Sub
Public Sub ShippingListAddTo()
End Sub
Public Sub ShippingThatDO()
End Sub
Public Sub ShippingThisDo()
End Sub
Public Sub ProductionListGet()
End Sub
Public Sub ProductionListAddTo()
End Sub
Public Sub ProductionThisDo()
End Sub
Public Sub ProductionThatDo()
End Sub
End Class
Keep in mind, some people consider that difficult to read. I personally prefer organization along those lines so when the methods are sorted alphabetically they group logically.
I have found the solution I was looking for using interfaces
Public Interface ICompany
Function Company_List() As DataTable
End Interface
Public Class MainClass
Public Company As ICompany = New CompanyClass
Public Sub New()
MyBase.New()
End Sub
Private Class CompanyClass
Public Sub New()
MyBase.New()
End Sub
Public Function Company_List() As DataTable
My code....
End Function
End Class
End Class