fun with oop

I would like to be able to pass a string into a method and have that method decide which kind of object to return.  For example,  I would like to pass the "woof" string into a method like the one illustrated below and have it return a "dog" object.  Is such a thing possible

I know that I can set the function return type to "Animal" since all three objects are derived from animal, but if I do that I will lose functionality in the "Parrot" object which inherits first from "Animal" then from "Bird".  For example, I would lose the ability to write "a.Wings" to the console (illustrated below) because the base class "Animal" does not have the ".Wings" property which resides in the more specific "Bird" class.

Another option would be to set the function return type to "Object".  This seems like a far from elegant solution.  Isn't there something more interesting I could do with Generics or some other cool new feature of VB 2005



 Function GetObject(ByVal speak As String) As Animal   'or Object
Select Case speak
Case "woof"

'Inherits Animal
Dim
d As New dog
d.color = brown
d.legs = 4
Return d

Case "meow"

'Inherits Animal
Dim
c As New cat
c.color = black
c.legs = 4
Return c

Case "polly wants a cracker"

'Inherits Animal ==> Bird
Dim
p As New parrot
p.color = brown
p.legs = 2
p.wings = 2
Return p

End Select

End Function


 


 Sub WriteToConsole(ByVal a As Animal)
Dim writeString As String
writeString = "Color: " & a.Color & ", " & "Legs: " & a.legs
'can't write a.Wings to console from animal object
'since this property is inherited from the bird class
Console.WriteLine(writeString)

End Sub


 



Answer this question

fun with oop

  • dbsize

    This is very nice code, but I don't see where it addresses my question. I was hoping to pass a string parameter to a method and have the method return the correct object type. Anyone
  • Knagis

    Public NotInheritable Class AnimalFactory
    Public Shared Sub Main()
    Dim ark As New List(Of Animal)
    Dim ns As String = GetType(Animal).Namespace
    ark.Add(AnimalFactory.Create(ns &
    ".Human"))
    ark.Add(AnimalFactory.Create(ns &
    ".Bird"))
    ark.Add(AnimalFactory.Create(ns &
    ".Cat"))
    ark.Add(AnimalFactory.Create(ns &
    ".Parrot"))
    ark.Add(AnimalFactory.Create(ns &
    ".Dog"))
    For Each beast As Animal In ark
    Console.WriteLine(beast.ToString())
    Next
    Console.ReadLine()
    End Sub

    Public
    Shared Function Create(ByVal animalname As String) As Animal
    Dim t As Type = Type.GetType(animalname, True, True)
    Dim args As String() = {animalname}
    Return Activator.CreateInstance(t, args)
    End Function
    End Class

    Public
    Class BodyParts
    Private constituentParts As New List(Of BodyParts)

    Public
    Sub New()
    End Sub

    Public
    Sub New(ByVal name As String)
    nameValue = name
    End Sub

    Private
    nameValue As String
    Public ReadOnly Property Name() As String
    Get
    Return nameValue
    End Get
    End Property

    Public
    Overrides Function ToString() As String
    If constituentParts.Count = 0 Then _
    Return nameValue & vbNewLine
    Dim s As String = String.Format("{0} has {1} parts{2}", _
    nameValue, constituentParts.Count, vbNewLine)
    For Each parts As BodyParts In constituentParts
    s += vbTab + parts.ToString()
    Next
    Return s
    End Function

    Public
    Sub Add(ByVal parts As BodyParts)
    constituentParts.Add(parts)
    End Sub
    End
    Class

    Public
    MustInherit Class Animal
    Inherits BodyParts

    Public
    Sub New()
    MyBase.New()
    End Sub

    Public
    Sub New(ByVal name As String)
    MyBase.New(name)
    Build()
    End Sub

    Protected
    MustOverride Sub Build()

    Public
    Overridable Function Speak() As String
    Return ""
    End Function

    Public
    Overrides Function ToString() As String
    Return String.Format("{0} says: '{1}'{2}{3}", _
    Me.Name, Me.Speak, vbNewLine, MyBase.ToString)
    End Function
    End
    Class

    Public
    MustInherit Class FourLegged
    Inherits Animal

    Public
    Sub New(ByVal name As String)
    MyBase.New(name)
    End Sub

    Protected
    Overrides Sub Build()
    Dim frontlegs As New BodyParts("front legs")
    frontlegs.Add(
    New BodyParts("left front"))
    frontlegs.Add(
    New BodyParts("right front"))
    Dim hindlegs As New BodyParts("hind Legs")
    hindlegs.Add(
    New BodyParts("left hind"))
    hindlegs.Add(
    New BodyParts("right hind"))
    Me.Add(frontlegs)
    Me.Add(hindlegs)
    End Sub
    End
    Class

    Public MustInherit Class TwoLegged
    Inherits Animal

    Public Sub New(ByVal name As String)
    MyBase.New(name)
    End Sub

    Protected Overrides Sub Build()
    Dim legs As New BodyParts("legs")
    legs.Add(
    New BodyParts("left leg"))
    legs.Add(
    New BodyParts("right leg"))
    Me.Add(legs)
    End Sub
    End
    Class

    Public Class Cat
    Inherits FourLegged

    Public Sub New(ByVal name As String)
    MyBase.New(name)
    End Sub

    Public Overrides Function Speak() As String
    Return "Meow"
    End Function
    End
    Class

    Public Class Dog
    Inherits FourLegged

    Public Sub New(ByVal name As String)
    MyBase.New(name)
    End Sub

    Public Overrides Function Speak() As String
    Return "Woof"
    End Function
    End
    Class

    Public Class Bird
    Inherits TwoLegged

    Public Sub New(ByVal name As String)
    MyBase.New(name)
    End Sub

    Protected Overrides Sub Build()
    MyBase.Build()
    Dim wings As New BodyParts("wings")
    wings.Add(
    New BodyParts("left wing"))
    wings.Add(
    New BodyParts("right wing"))
    Me.Add(wings)
    End Sub

    Public Overrides Function Speak() As String
    Return "Tweet"
    End Function
    End
    Class

    Public Class Parrot
    Inherits Bird

    Public Sub New(ByVal name As String)
    MyBase.New(name)
    End Sub

    Public Overrides Function Speak() As String
    Return "Polly want a cracker"
    End Function
    End
    Class

    Public Class Human
    Inherits TwoLegged

    Public Sub New(ByVal name As String)
    MyBase.New(name)
    End Sub

    Protected Overrides Sub Build()
    MyBase.Build()
    Dim arms As New BodyParts("arms")
    arms.Add(
    New BodyParts("left arm"))
    arms.Add(
    New BodyParts("right arm"))
    Me.Add(arms)
    End Sub

    Public Overrides Function Speak() As String
    Return "Hello!"
    End Function
    End Class



  • jacco2

    remember, ToString is a virtual method of object. override it for all your classes.



  • Matthew Weyland

    hmmm. . . Actually it does. . . well not directly. You could change AnimalFactory to this:

    Public NotInheritable Class AnimalFactory
    Public Shared Sub Main()
    Dim ark As New List(Of Animal)
    Dim ns As String = GetType(Animal).Namespace
    ark.Add(AnimalFactory.Create(ns &
    ".Human"))
    ark.Add(AnimalFactory.Create(ns &
    ".Bird"))
    ark.Add(AnimalFactory.Create(ns &
    ".Cat"))
    ark.Add(AnimalFactory.Create(ns &
    ".Parrot"))
    ark.Add(AnimalFactory.Create(ns &
    ".Dog"))
    Console.WriteLine(
    "Ark loaded by class name. . . ")
    Console.WriteLine(
    New String("-", 25))
    For Each beast As Animal In ark
    Console.WriteLine(beast.ToString())
    Next
    ark.Clear()
    ark.Add(AnimalFactory.CreateBySound(
    "Hello"))
    ark.Add(AnimalFactory.CreateBySound(
    "Tweet"))
    ark.Add(AnimalFactory.CreateBySound(
    "Meow"))
    ark.Add(AnimalFactory.CreateBySound(
    "Polly want a cracker"))
    ark.Add(AnimalFactory.CreateBySound(
    "Woof"))
    Console.WriteLine(
    New String("-", 25))
    Console.WriteLine(
    "Ark loaded by animal sound. . . ")
    Console.WriteLine(
    New String("-", 25))
    For Each beast As Animal In ark
    Console.WriteLine(beast.ToString())
    Next
    Console.ReadLine()
    End Sub

    Public Shared Function Create(ByVal animalname As String) As Animal
    Dim t As Type = Type.GetType(animalname, True, True)
    Dim args As String() = {animalname}
    Return Activator.CreateInstance(t, args)
    End Function

    Public Shared Function CreateBySound(ByVal sound As String) As Animal
    Dim ns As String = GetType(Animal).Namespace
    Select Case sound.ToUpper()
    Case "HELLO"
    Return AnimalFactory.Create(ns & ".Human")
    Case "TWEET"
    Return AnimalFactory.Create(ns & ".Bird")
    Case "MEOW"
    Return AnimalFactory.Create(ns & ".Cat")
    Case "POLLY WANT A CRACKER"
    Return AnimalFactory.Create(ns & ".PARROT")
    Case "WOOF"
    Return AnimalFactory.Create(ns & ".Dog")
    Case Else
    Throw New ArgumentException("Unknown Sound")
    End Select
    End Function
    End
    Class

    The point is. . .

    this is not OOP:

    Sub WriteToConsole(ByVal a As Animal)

    Dim writeString As String
    writeString = "Color: " & a.Color & ", " & "Legs: " & a.legs
    'can't write a.Wings to console from animal object
    'since this property is inherited from the bird class
    Console.WriteLine(writeString)

    End Sub

    Your class should know how to write itself via Animal.ToString() or Animal.WriteToConsole()

    I suggest you run the code I posted.



  • fun with oop