2016-08-15 92 views
0

我已經提出了一個問題here,我基本上需要將基類的實例轉換爲子類(或使用基類屬性的實例創建的子類的新實例)。結論似乎是這樣做的最好方法是手動分配我需要在基類的構造函數中傳輸的每個屬性。爲什麼VB不允許從父類到子類的類型轉換?

儘管在某些情況下這是可行的,但它並不是在有很多屬性需要傳輸時,或者基類可能會發生變化時 - 每次向基類添加屬性時,構造函數都需要也改變了,所以這個解決方案不夠優雅。

我已經在網上搜索,並且看不到爲什麼這種類型鑄造沒有實現的任何理由。我迄今爲止所看到的論點描述了這種操作「沒有任何意義」(從汽車中製作小型貨車就是我看到的一個類比),質疑如何處理子類中的非繼承變量,或者聲稱必須爲嘗試實現的目標提供更好的解決方案。

據我所知,只要有用,操作不需要「有意義」,所以這不是一個很好的理由。添加更多屬性(也許方法/覆蓋它們)將實例更改爲子類有什麼不妥?在非繼承變量的情況下,只需通過允許這種類型轉換就可以解決這個問題 - 只需將一個構造函數添加到子類中,或者只需將它們設置爲其默認值。畢竟,施工人員通常都會撥打MyBase.New(...)。使用基礎構造函數(基本上創建基礎的新實例)和使用已經初始化的實例之間有什麼區別?最後,我不認爲第三個論點是合理的 - 有些時候所有其他解決方案都不夠優雅。

所以最後,還有什麼其他理由爲什麼這種鑄造不被允許,並且有沒有一種優雅的方法來規避這種情況?

編輯:

因爲我不知道了很多關於這個話題,我想我的意思是說「轉換」,而不是「投」。我還會添加一個示例來展示我試圖成功的方式。只有在子類別初始化時才允許轉換:

Class BaseClass 

Dim x as Integer 
Dim y as Integer 

End Class 


Class Subclass1 : Inherits BaseClass 

    Dim z as Integer 

    Sub New(Byval value As Integer) 
     'Standard initialisation method 

     MyBase.New() 

     z = value 
    End Sub 

    Sub New(Byval value As Integer, Byval baseInstance As BaseClass) 
     'Type conversion from base class to subclass 

     baseInstance.passAllproperties() 
'This assigns all properties of baseInstance belonging to BaseClass to Me. 
'Properties not in BaseClass (eg. if baseInstance is Subclass2) are ignored. 

     z = value 
    End Sub 
End Class 


Class Subclass2 : Inherits BaseClass 

    Dim v As Integer 
End Class 
+2

您需要更好地理解繼承和多態。你不能將基礎投射到後代,因爲通常不可能這樣做。你怎麼能把一隻動物當成一匹馬來對待它,當那隻動物可能是一隻貓或一隻海豹?當你試圖把馬鞍和馬繮放在他們身上並將他們騎在你的院子周圍時,貓和海豹會極力反對。如果你發現自己需要這樣做,這是你的課程設計或實施得不好的跡象。 –

+0

@KenWhite我不同意。後裔在初始化時要求基地的一個實例用作模板有什麼問題? – Shuri2060

+0

雖然這不是你的問題所要求的。你的問題是關於**基地**被投給**後代**,這是**完全相反的**。對於後代來說,要求父母(基礎)實例是很好的;例如,它在調用基礎構造函數時定期完成。你曾經問過做相反的事,這是你失敗的地方。 –

回答

1

使用System.Reflection遍歷屬性和基類的領域,並將其應用到派生類。此示例包含單個公共財產和單個公共領域,但也將與多個私有/受保護的屬性和字段一起使用。您可以將整個示例粘貼到新的控制檯應用程序中進行測試。

Imports System.Reflection 

Module Module1 

    Sub Main() 
     Dim p As New Parent 
     p.Property1 = "abc" 
     p.Field1 = "def" 
     Dim c = New Child(p) 
     Console.WriteLine("Property1 = ""{0}"", Field1 = ""{1}""", c.Property1, c.Field1) 
     Console.ReadLine() 
    End Sub 

    Class Parent 
     Public Property Property1 As String = "not set" 
     Public Property Field1 As String = "not set" 
    End Class 

    Class Child 
     Inherits Parent 
     Public Sub New(myParent As Parent) 
      Dim fieldInfo = GetType(Parent).GetFields(BindingFlags.NonPublic _ 
                 Or BindingFlags.Instance) 
      For Each field In fieldInfo 
       field.SetValue(Me, field.GetValue(myParent)) 
      Next 
      Dim propertyInfo = GetType(Parent).GetProperties(BindingFlags.NonPublic _ 
                  Or BindingFlags.Instance) 
      For Each prop In propertyInfo 
       prop.SetValue(Me, prop.GetValue(myParent)) 
      Next 
     End Sub 
    End Class 

End Module 

輸出:

該解決方案是自動化的,所以你不需要改變任何添加或刪除時

Property1 = 「ABC」,字段1 = 「高清」屬性和基類中的字段。

+0

正如我所說的,我不想做這樣的事情,因爲每當編輯父類改變其屬性,所有執行此操作的孩子也必須修改。 – Shuri2060

+0

然後使用反射遍歷屬性和字段(甚至私有),並將找到的所有內容都設置爲派生類。 – djv

+0

你能鏈接我的例子或鏈接解釋這個?我只能找到c# – Shuri2060

3

您描述的內容不是轉換。你有沒有聽過「用不同的光線投射東西」這個表達方式?它意味着用不同的方式看待同一件事,或者讓同樣的事情看起來不同。這是編程中使用術語「投射」的確切方式。在投射時,您不會更改對象的類型,而只會改變用於訪問對象的參考的類型。如果你想從一個基類型轉換爲派生類型,那麼你所指的對象實際上就是那個派生類型。如果不是那麼你不是演員,而是轉換。

那麼,爲什麼不能將基類型的實例轉換爲派生類型的實例。那麼,你爲什麼能夠?是的,這可能會節省時間編寫一些代碼,但它確實有意義嗎?假設您有一個基本類型和一個屬性,並且派生類型添加了另一個屬性。我們還要說,派生類型具有要求您爲第二個屬性提供值的構造函數。您建議該語言應該爲您提供一種將基類的實例魔術轉換爲派生類的實例的方法,這意味着它必須放慢您規避由作者通過構造函數定義的規則。爲什麼這會是一件好事?

+0

好的 - 因爲我對這個知之甚少,所以把它叫做錯誤的名字。但至於第二點,我說你應該能夠通過爲子類創建一個新的初始化器來將一個基類轉換爲子類,該初始化器將基類的一個實例作爲參數。我沒有看到這與你如何調用MyBase.New(...)或super.init(...)有什麼不同。)'(取決於語言) - 您仍然需要初始化該初始化程序中的任何非繼承變量,因此您必須爲新屬性提供一個值。 – Shuri2060

+0

@QuestionAsker:這不是*鑄造*,它與將基類轉換爲子類*無關。它被稱爲*遺傳*,在那裏(就像你從你父母或祖父母那裏得到的那樣),你**繼承你的祖先的資產。正如我所說的,你需要更好地理解繼承和多態。 –

0

在一般情況下,因爲這樣:

Class TheBase 
End Class 

Class Derived1 : TheBase 
    Sub Foo() 
    End Sub 
End Class 

Class Derived2 : TheBase 
    Sub Bar() 
    End Sub 
End Class 

Sub Main() 
    Dim myDerived1 As New Derived1 
    ' cast derived to base 
    Dim myTheBase = CType(myDerived1, TheBase) 
    ' cast base to derived? 
    ' but myTheBase is actually a Derived1 
    Dim myDerived2 As Derived2 = CType(myTheBase, Derived2) 
    ' which function call would you like to succeed? 
    myDerived2.Foo() 
    myDerived2.Bar() 
End Sub 
+0

我澄清了我在OP中的意思 - 我的意思是轉換而不是鑄造。所以在從Base轉換到Subclass之後,只有屬於Base的屬性纔會被轉移。因此'myDerived2.Foo'將不存在。 – Shuri2060

+0

這裏的要點是構建的唯一對象是Derived1。它不能更改爲Derived2,因爲它們可能有很多差異。你可以編寫自己的方法來做到這一點,現在每個人都知道你不是在談論鑄造。 – djv

相關問題