none
關於建制抽象化類別的作法 RRS feed

  • 問題

  • 各位 大大們好:

    我想要請教一個關於 MustOverride 的問題
    我按書上的教學打  但是在
    Public Class Sub_TagsClass(Of tType) : Inherits Abstract_TagsClass(Of tType) '繼承 Abstract_TagsClass 
    會出現沒有Overloads的問題,請問我應該怎麼解決這個問題呢



    'Option Explicit On

    'Tags Class 點群的
    Public MustInherit Class Abstract_TagsClass(Of tType)
        ' MustOverride 被定義成可以被多重覆寫的
        Public MustOverride Function Set_TagInfo(ByVal nIdx As Byte, ByVal nSetData As tType) As tType
        Public MustOverride Function Get_TagInfo(ByVal nIdx As tType) As tType

        Private Tags As TagStructure
        Structure TagStructure
            '點序號
            Public TagIndex As tType ' UInt32

            '點群組 0~255組可用
            Public TagGroup As tType ' Byte
        End Structure

        Public Property Setting(ByVal nIdx As Byte) As tType
            Get
                Select Case nIdx
                    Case 0 '設定該點的Index 
                        Return Tags.TagIndex
                    Case 1 '設定該點的群組代號
                        Return Tags.TagGroup
                End Select
            End Get
            Set(ByVal nSetData As tType)
                Select Case nIdx
                    Case 0 '設定該點的Index  
                        Tags.TagIndex = nSetData
                    Case 1 '設定該點的群組代號
                        Tags.TagGroup = nSetData
                End Select
            End Set
        End Property

    End Class

    Public Class Sub_TagsClass(Of tType) : Inherits Abstract_TagsClass(Of tType) '繼承 Abstract_TagsClass 

        '點的種類
        Public TagType As tType ' Byte
        '點名稱
        Public TagName As tType ' String

        Public Overrides Function Set_TagInfo(ByVal nIdx As Byte, ByVal nSetData As tType) As tType
            Select Case nIdx
                Case 0 '設定該點的種類
                    TagType = nSetData
                Case 1 '設定該點的名稱 
                    TagName = nSetData
            End Select
        End Function

        Public Overloads Function Get_TagInfo(ByVal nIdx As Byte) As tType
            Select Case nIdx
                Case 0 '設定該點的種類
                    Return TagType
                Case 1 '設定該點的名稱 
                    Return TagName
            End Select
        End Function


    End Class




    嗯 還有一個問題是

    小弟想做一個模型是

             base Class (Socket 基礎連線)  <<<<  Sub Class (不同的連線方法)  就是  我可以架構在 Base Class 下隨時可以創造出不同的連線方法

             而 每一種連線方法 他可以 引用  另外一個  Base Class (Tag資料 事件)  Sub Class(點屬性 方法)


    不曉得 我上面這樣撰寫有沒有辦法達到呢  


    以上麻煩各位了 謝謝 ^^
    2009年6月27日 上午 02:27

解答

  • 你要這樣做當然也是可以,同樣結果的程式本來就有許多不同的方式可以開發,大家可以選擇適合自己﹝或自己喜歡的方式﹞去開發。
    如果你想以這種想法去開發,我認為首要並不是去討論怎麼寫介面 或 抽象類別,而是應該先把基礎觀念弄通。不知道你有沒有看過「倚天屠龍記」這本小說,其中有一段說到張無忌學乾坤大挪移的故事,心法上寫著:「第一層心法悟心高者七年可成,次者十四年可成。」可是張無忌毫不費力就學會了,原因在於他身負九陽神功。這和寫程式一樣,初期去看這些抽象類別或介面的程式碼一定會看的莫名其妙,但是當你先去研究別人的範例,瞭解關鍵字的用法、瞭解類別與介面之間的關係;那寫起程式來就是水道渠成了。
    個人認為現階段你需要多瞭解這些東西的內涵,我找了幾個文章的連結供你參考:
    MSDN 文件庫
    [Visual Basic 程式設計手冊 何時使用介面]
    [Visual Basic 程式設計手冊 何時使用繼承]
    [Visual Basic 程式設計手冊 介面概觀]
    [Visual Basic 程式設計手冊 介面定義]

    Allen Kuo [何時要使用父類別,何時要使用interface(介面)]
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    • 已標示為解答 Max197 2009年6月28日 上午 08:39
    2009年6月28日 上午 03:33
    版主
  • 其實我不是很了解你的意思,不過就個人的習慣而言,我會把連線通訊做成一個獨立的類別﹝假設類別名稱叫 mySocketClass﹞,當我有一個新的設備要連接﹝例如是個數位電表好了﹞,可能會先建立一個 數位電表專用的類別,在此類別中要用到通訊時,並不會用繼承的方法,而是在電表類別中產生mySocketClass的執行個體,藉由呼叫這個執行個體來做通訊。


    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    • 已標示為解答 Max197 2009年6月27日 上午 09:29
    2009年6月27日 上午 06:44
    版主
  • 其實要寫的物件導向並不是很容易的事情,因為這牽涉到的還不是語法而已,有許多的觀念都需要建立。推薦你一本書[世紀末軟體革命復刻版:C++、GUI與物件導向理論],我覺得這本書對於物件導向的觀念解釋的頗清楚,你可以參考看看
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    • 已標示為解答 Max197 2009年6月28日 上午 08:38
    2009年6月28日 上午 06:17
    版主

所有回覆

  • 原因出在Overrides的規則:使用Overrides覆寫必需要傳入完全相同的參數  請參閱MSDN文件庫 [Visual Basic 語言參考 Overrides]
    你在基底類別 宣告 Public MustOverride Function Get_TagInfo(ByVal nIdx As tType) As tType
    那在繼承類別 就應該是    Public Overrides Function Get_TagInfo(ByVal nIdx As tType) As tType
    第二個問題等你有進一步結果再繼續討論吧
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    2009年6月27日 上午 04:30
    版主
  • 嗯嗯 我知道了  謝謝您:D
    我修正了   
    Public MustOverride Function Get_TagInfo(ByVal nIdx As Byte) As tType
        Public Overrides Function Get_TagInfo(ByVal nIdx As Byte) As tType


    不過我在外部引用

            Dim FF As Abstract_TagsClass(Of Integer)
            FF = New Abstract_TagsClass(Of Integer)
            FF.Set_TagInfo(0, 33)
            MessageBox.Show(FF.Get_TagInfo(0).ToString)

    他說 我不能引用 New 他說 因為包含一個尚未被複寫的 MustOverride 的成員 那我要怎麼動態新增呢 謝謝您




    'Tags Class 點群的
    Public MustInherit Class Abstract_TagsClass(Of tType)
        ' MustOverride 被定義成可以被多重覆寫的
        Public MustOverride Function Set_TagInfo(ByVal nIdx As Byte, ByVal nSetData As tType) As tType
        Public MustOverride Function Get_TagInfo(ByVal nIdx As Byte) As tType

        Private Tags As TagStructure
        Structure TagStructure
            '點序號
            Public TagIndex As tType ' UInt32

            '點群組 0~255組可用
            Public TagGroup As tType ' Byte
        End Structure

        'Private Sub New()
        '    初始化
        '    Debug.WriteLine("Index" & Tags.TagIndex.ToString() & "  Group: " & Tags.TagGroup.ToString())
        'End Sub

        Public Property Setting(ByVal nIdx As Byte) As tType
            Get
                Select Case nIdx
                    Case 0 '設定該點的Index 
                        Return Tags.TagIndex
                    Case 1 '設定該點的群組代號
                        Return Tags.TagGroup
                End Select
            End Get
            Set(ByVal nSetData As tType)
                Select Case nIdx
                    Case 0 '設定該點的Index  
                        Tags.TagIndex = nSetData
                    Case 1 '設定該點的群組代號 
                        Tags.TagGroup = nSetData
                End Select
            End Set
        End Property

    End Class

    MustInherit Class Sub_TagsClass(Of tType) : Inherits Abstract_TagsClass(Of tType) '繼承 Abstract_TagsClass 

        '點的種類
        Public TagType As tType ' Byte
        '點名稱
        Public TagName As tType ' String


        Public Overrides Function Set_TagInfo(ByVal nIdx As Byte, ByVal nSetData As tType) As tType
            Select Case nIdx
                Case 0 '設定該點的種類
                    TagType = nSetData
                Case 1 '設定該點的名稱 
                    TagName = nSetData
            End Select
        End Function

        Public Overrides Function Get_TagInfo(ByVal nIdx As Byte) As tType
            Select Case nIdx
                Case 0 '設定該點的種類
                    Return TagType
                Case 1 '設定該點的名稱 
                    Return TagName
            End Select
        End Function


    End Class

    2009年6月27日 上午 05:22

  • 不過我在外部引用

            Dim FF As Abstract_TagsClass(Of Integer)
            FF = New Abstract_TagsClass(Of Integer)
            FF.Set_TagInfo(0, 33)
            MessageBox.Show(FF.Get_TagInfo(0).ToString)

    他說 我不能引用 New 他說 因為包含一個尚未被複寫的 MustOverride 的成員 那我要怎麼動態新增呢 謝謝您


      因為 Abstract_TagsClass 你宣告為 MustInherit ,有這個關鍵字的類別只能當做基底類別﹝也就是只能新建一個類別繼承它﹞,是無法從這個類別建立物件的。如果你的類別是要能建立執行個體的,就不能加上MustInherit 。
     詳情請參閱 MSDN文件庫 [Visual Basic 語言參考 MustInherit]

    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    2009年6月27日 上午 05:52
    版主
  • 對厚  這樣我瞭解了


    那第二個問題能請您給我一點建議嗎??

    我現在  需要創造一個Class 我想可能要用 介面才可以 多重宣告了

    Socket Class  用於與設備連線的用途  且該 Class 底下 需要可以隨時創造 不同的 〔方法〕
    我的意思是  當有新的連線方法  我只要繼承 Socket Class 就可以動態產生 網路的基本連線

    然後透過每個方法獨立作不同的網路傳輸介面  例如 方法一: 上傳檔案  方法二: 下載檔案

    但 每個方法 都有其子 sub class  就是 該方法會有一個 sub Class 用來存放資訊用的


    Socket Class -> Sub Class(方法) -> 屬性


    不曉得 這樣說您是否瞭解我的意思麻煩您開示一下了 謝謝 :D
    2009年6月27日 上午 06:26
  • 其實我不是很了解你的意思,不過就個人的習慣而言,我會把連線通訊做成一個獨立的類別﹝假設類別名稱叫 mySocketClass﹞,當我有一個新的設備要連接﹝例如是個數位電表好了﹞,可能會先建立一個 數位電表專用的類別,在此類別中要用到通訊時,並不會用繼承的方法,而是在電表類別中產生mySocketClass的執行個體,藉由呼叫這個執行個體來做通訊。


    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    • 已標示為解答 Max197 2009年6月27日 上午 09:29
    2009年6月27日 上午 06:44
    版主
  • 嗯嗯 是的  就是您的作法

    我需要建制的就是

    底下的類別需要通訊的時候去呼叫 mySocketClass 的執行體


    那我要怎麼建構您的想法呢??


    2009年6月27日 上午 07:09
  • 您好 請問我這樣建制  恰當嗎 ??

    麻煩您幫我健檢一下 謝謝您 :D

       '通訊介面
        Public Interface ScoketProperty
            Property sIP() As String   'IP位置 
            Property sHost() As String '主機名稱
            Property sPort() As UShort 'Port 位置
        End Interface

        Public Interface SocketModel

            '繼承屬性型別
            Inherits ScoketProperty

            '通訊協定 M1
            Sub M1()
            '通訊協定 P1
            Sub P1()

        End Interface


        Public Class User
            Implements SocketModel

            Public Property sHost() As String Implements ScoketProperty.sHost
                Get
                    Return Me.sHost
                End Get
                Set(ByVal value As String)
                    Me.sHost = value
                End Set
            End Property

            Public Property sIP() As String Implements ScoketProperty.sIP
                Get
                    Return Me.sIP
                End Get
                Set(ByVal value As String)
                    Me.sIP = value   //這邊會出現    運算式呼叫遞迴的屬性  這樣是正常的嗎  ?? 
                End Set
            End Property

            Public Property sPort() As UShort Implements ScoketProperty.sPort
                Get
                    Return Me.sPort
                End Get
                Set(ByVal value As UShort)
                    Me.sPort = value
                End Set
            End Property

            Public Sub M1() Implements SocketModel.M1

            End Sub

            Public Sub P1() Implements SocketModel.P1

            End Sub
        End Class
    2009年6月27日 上午 10:04
  • 這種例子其實不是很好舉例,以下的範例恐怕也不是太好,不過我覺得應該是按步就班來,畢竟自訂Interface和Class除了會寫程式之外還需要其它的經驗,才能寫出一個合理且合用的Interface 或 Class ,可以從建立自訂Class下手,以下是一個範例
    ===================================================
    我先建立一個 mySocketClass
    Imports System.Net
    Imports System.Net.Sockets
    Public Class mySocketClass
        Private m_Ip As String
        Public Property _Ip() As String
            Get
                Return m_Ip
            End Get
            Set(ByVal value As String)
                m_Ip = value
            End Set
        End Property

        Private m_Port As Integer
        Public Property _Ports() As Integer
            Get
                Return m_Port
            End Get
            Set(ByVal value As Integer)
                m_Port = value
            End Set
        End Property
        Private m_Socket As Socket
        Public Property _Socket() As Socket
            Get
                Return m_Socket
            End Get
            Set(ByVal value As Socket)
                m_Socket = value
            End Set
        End Property

        Public Sub New(ByVal strIP As String, ByVal iPort As Integer)
            m_Ip = strIP
            m_Port = iPort
            m_Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            m_Socket.Connect(IPAddress.Parse(strIP), iPort)
        End Sub
        Public Function SendData(ByVal mySendBytes() As Byte) As Integer
            Dim iSendBytes As Integer
            iSendBytes = m_Socket.Send(mySendBytes, mySendBytes.Length, SocketFlags.None)
        End Function
    End Class

    =================================================
    第二個是建立一個 myCalcClass,其中利用到 mySocketClass來通訊
    Imports System.Text
    Public Class myCalcClass
        Private m_Ip As String
        Public Property _Ip() As String
            Get
                Return m_Ip
            End Get
            Set(ByVal value As String)
                m_Ip = value
            End Set
        End Property

        Private m_Port As Integer
        Public Property _Ports() As Integer
            Get
                Return m_Port
            End Get
            Set(ByVal value As Integer)
                m_Port = value
            End Set
        End Property

        Private m_Data As String
        Public Property _data() As String
            Get
                Return m_Data
            End Get
            Set(ByVal value As String)
                m_Data = value
            End Set
        End Property
        Private m_mysocket As mySocketClass
        Public Property _mysocket() As mySocketClass
            Get
                Return m_mysocket
            End Get
            Set(ByVal value As mySocketClass)
                m_mysocket = value
            End Set
        End Property

        Sub New(ByVal strIP As String, ByVal iPort As Integer, ByVal strSendString As String)
            m_Ip = strIP
            m_Port = iPort
            m_Data = strSendString
            m_mysocket = New mySocketClass(m_Ip, m_Port)
        End Sub
        Public Function SendString() As Integer
            m_mysocket.SendData(GetSendBytes())
        End Function
        Private Function GetSendBytes() As Byte()
            Dim myBytes() As Byte
            myBytes = Encoding.GetEncoding(950).GetBytes(m_Data)
            Return myBytes
        End Function

    End Class
    ============================================================
    這是在Form中的程式
    Public Class Form1

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim myCalc As New myCalcClass("127.0.0.1", 9999, "測試")
            myCalc.SendString()
        End Sub
    End Class
    =================================================
    另外關於你以下這個的問題
    Public Property sIP() As String Implements ScoketProperty.sIP

               Get
                    Return Me.sIP
                End Get
                Set(ByVal value As String)
                    Me.sIP = value   //這邊會出現    運算式呼叫遞迴的屬性  這樣是正常的嗎  ?? 
                End Set
            End Property
    這樣變成自己等於自己,所以基本上不合理 ,關於屬性的使用可以參閱 MSDN文件庫[HOW TO:在 Visual Basic 中宣告及呼叫預設屬性] 以及相關連結﹝這個Page底下有個請參閱﹞

    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    2009年6月27日 上午 11:00
    版主
  •    '通訊介面
        Public Interface ScoketProperty
            Property sIP() As String   'IP位置 
            Property sHost() As String '主機名稱
            Property sPort() As UShort 'Port 位置
        End Interface

        Public Interface SocketModel

            '繼承屬性型別
            Inherits ScoketProperty

            '通訊協定 M1
            Sub M1()
            '通訊協定 P1
            Sub P1()
        End Interface

    其實我的想法是如果可以的話,把整個Abstract_TagsClass與這個SocketClass 透過介面整併成一個介面  雖然這樣可能要在其他 Class 實做用不到的 Function 或 Sub
    但是這樣是我想到可以整合在一起的方法

    以後在 From   
     
    Dim myCalc() As  myCalcClass()
    Redim myCalc(10)
    myCalc(0) = new myCalcClass("127.0.0.1", 1, "測試1")
    myCalc(1) = new myCalcClass("127.0.0.2", 2, "測試2")
    myCalc(0).SendString()
    myCalc(1).SendString()

    也可以類似上面這樣呼叫  多載可以這樣用嗎

    如此 我就可以根據   Abstract_TagsClass 作條件篩選後  決定 用什麼模式去作 SocketClass
    然後這個SocketClass 所皆收到與傳送的資料與 Abstract_TagsClass 可以是同步的
    而且我可以透過Thread來做這件事  
    您覺得這樣可行嗎?謝謝您
    ps: 為什麼我Enter換行後 打得 字會自動變大呢?? 怪怪 呵
    • 已編輯 Max197 2009年6月28日 上午 02:55
    2009年6月28日 上午 02:54
  • Public Property sIP() As String Implements ScoketProperty.sIP

               Get
                    Return Me.sIP
                End Get
                Set(ByVal value As String)
                    Me.sIP = value   //這邊會出現    運算式呼叫遞迴的屬性  這樣是正常的嗎  ?? 
                End Set
            End Property
    這樣變成自己等於自己,所以基本上不合理 ,關於屬性的使用可以參閱 MSDN文件庫[HOW TO:在 Visual Basic 中宣告及呼叫預設屬性] 以及相關連結﹝這個Page底下有個請參閱﹞


    可是因為  Public Property sIP() As String Implements ScoketProperty.sIP 是程式自己產生的
    那我是應該 在創見一個  Function 去對應 介面那邊的屬性嗎??  
        Public Interface ScoketProperty
            Property sIP() As String   'IP位置 
            Property sHost() As String '主機名稱
            Property sPort() As UShort 'Port 位置
        End Interface

    例如
        Public Interface ScoketProperty
            Property sIP() As String   'IP位置 
            Property sHost() As String '主機名稱
            Property sPort() As UShort 'Port 位置
        End Interface


        public mIP as String
        Public Property sIP() As String Implements ScoketProperty.sIP

               Get
                    Return mIP
                End Get
                Set(ByVal value As String)
                    mIP = value   //這邊會出現    運算式呼叫遞迴的屬性  這樣是正常的嗎  ?? 
                End Set
            End Property

        end Property

        sub Change ()
    me.sIP = mIP
        end sub
    2009年6月28日 上午 03:10
  • 你要這樣做當然也是可以,同樣結果的程式本來就有許多不同的方式可以開發,大家可以選擇適合自己﹝或自己喜歡的方式﹞去開發。
    如果你想以這種想法去開發,我認為首要並不是去討論怎麼寫介面 或 抽象類別,而是應該先把基礎觀念弄通。不知道你有沒有看過「倚天屠龍記」這本小說,其中有一段說到張無忌學乾坤大挪移的故事,心法上寫著:「第一層心法悟心高者七年可成,次者十四年可成。」可是張無忌毫不費力就學會了,原因在於他身負九陽神功。這和寫程式一樣,初期去看這些抽象類別或介面的程式碼一定會看的莫名其妙,但是當你先去研究別人的範例,瞭解關鍵字的用法、瞭解類別與介面之間的關係;那寫起程式來就是水道渠成了。
    個人認為現階段你需要多瞭解這些東西的內涵,我找了幾個文章的連結供你參考:
    MSDN 文件庫
    [Visual Basic 程式設計手冊 何時使用介面]
    [Visual Basic 程式設計手冊 何時使用繼承]
    [Visual Basic 程式設計手冊 介面概觀]
    [Visual Basic 程式設計手冊 介面定義]

    Allen Kuo [何時要使用父類別,何時要使用interface(介面)]
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    • 已標示為解答 Max197 2009年6月28日 上午 08:39
    2009年6月28日 上午 03:33
    版主
  • 你要這樣做當然也是可以,同樣結果的程式本來就有許多不同的方式可以開發,大家可以選擇適合自己﹝或自己喜歡的方式﹞去開發。
    如果你想以這種想法去開發,我認為首要並不是去討論怎麼寫介面 或 抽象類別,而是應該先把基礎觀念弄通。不知道你有沒有看過「倚天屠龍記」這本小說,其中有一段說到張無忌學乾坤大挪移的故事,心法上寫著:「第一層心法悟心高者七年可成,次者十四年可成。」可是張無忌毫不費力就學會了,原因在於他身負九陽神功。這和寫程式一樣,初期去看這些抽象類別或介面的程式碼一定會看的莫名其妙,但是當你先去研究別人的範例,瞭解關鍵字的用法、瞭解類別與介面之間的關係;那寫起程式來就是水道渠成了。
    個人認為現階段你需要多瞭解這些東西的內涵,我找了幾個文章的連結供你參考:
    MSDN 文件庫
    [Visual Basic 程式設計手冊 何時使用介面]
    [Visual Basic 程式設計手冊 何時使用繼承]
    [Visual Basic 程式設計手冊 介面概觀]
    [Visual Basic 程式設計手冊 介面定義]

    Allen Kuo [何時要使用父類別,何時要使用interface(介面)]
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
     嗯嗯 是啊  要分清楚這介面與繼承類別的定義
     我主要的想法是  TagClass 這裡只有一份 Tag 的資料 然後 當SocketClass 這邊有動作的時候也可以更新到
     (例如在SocketClass 用事件去讀寫 TagClass )

     最後把他們包在 Dll 內 以後要用的時候就可以很單純的 建好 TagClass 然後根據條件 去呼叫 SocketClass
     這樣就比較單純

     好得 我會好好研讀您給的連結, 謝謝您 :D
    2009年6月28日 上午 04:44
  • 其實要寫的物件導向並不是很容易的事情,因為這牽涉到的還不是語法而已,有許多的觀念都需要建立。推薦你一本書[世紀末軟體革命復刻版:C++、GUI與物件導向理論],我覺得這本書對於物件導向的觀念解釋的頗清楚,你可以參考看看
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    • 已標示為解答 Max197 2009年6月28日 上午 08:38
    2009年6月28日 上午 06:17
    版主
  • 其實要寫的物件導向並不是很容易的事情,因為這牽涉到的還不是語法而已,有許多的觀念都需要建立。推薦你一本書[世紀末軟體革命復刻版:C++、GUI與物件導向理論],我覺得這本書對於物件導向的觀念解釋的頗清楚,你可以參考看看
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    嗯嗯 謝謝您~~~ 我會去找這本書來看看~~  謝謝您的建議  受益良多 ^^
    2009年6月28日 上午 08:38