2014-02-26 94 views
1

爲什麼我無法訪問S類方法?爲什麼我能夠在M類中創建同名的方法?沒有得到這個繼承

public class S 
{ 
    public S() 
    { 
    } 

    public int myFunc(int a, int b) 
    { 
     return a + b; 
    } 
} 

public class M:S 
{ 
    public M() 
    { 
    } 

    public string myFunc(int a, int b) 
    { 
     return (a + b).ToString(); 
    } 
} 

public class Test 
{ 
    public static void Main(string[] args) 
    { 
     M mm = new M(); 
     mm.myFunc(1,2); // Why I am not able to access S class myFunc 
    } 
} 
+1

你爲什麼不理會從編譯器警告消息?你認爲這只是爲了讓編譯器開發者做些什麼嗎? –

回答

5

這被稱爲member hiding多餘的值。可以通過鑄造參考訪問S類方法:

public class Test 
{ 
    public static void Main(string[] args) 
    { 
     M mm = new M(); 
     string x = mm.myFunc(1,2);  // calls M.myFunc 
     int y = ((S)mm).myFunc(1,2); // calls S.myFunc 

     S ss = new M(); 
     int z = ss.myFunc(1,2);  // calls S.myFunc 
    } 
} 

限定派生類成員時,應使用的new modifier;否則,你會得到一個編譯器警告。

編輯:請注意,成員隱藏不同於多態。在成員隱藏中,類成員在編譯時基於聲明的類型的引用進行解析。在我上面的示例中,ss被聲明爲S,即使它實際上分配了M類型的實例。

要實現多態性,您需要在基類成員上指定virtual修飾符,並在派生類成員上指定override。因此,虛擬成員的調用在運行時被解析爲實例的實際類型。然而,多態性不允許你改變返回類型,所以你不能在你的例子中使用它。

3

因爲c#不會根據返回類型重載,只能根據名稱和參數進行重載。所以M重載S和S的myFunc變得無法訪問。請更改名稱或參數。

如果你將它轉換爲是你將失去M有

+0

我無法理解這一點。因爲首先我繼承S類,所以它的方法應該在類M中可用,並且如果它可用,那麼爲什麼我能夠在類M中創建具有相同方法。 –

+0

當您創建具有相同名稱的方法並且參數,它會自動重載它。例如S'方法在M中變得無法訪問。它隱藏了方法 – matthijsb

0

更改返回類型不會重載該方法(您不能在一個具有相同名稱和參數以及不同返回類型的類中使用兩個完全相同的方法)。

原因很明顯 - 如何決定,哪一個會被調用?

要重載某些東西,必須有不同的參數。

0

您將可以通過base.myFunc(1,2)訪問它;

+1

base在Main方法中不可訪問 – matthijsb

0

你需要投的對象是這樣的:

(S(mm)).myFunc(1, 2); // now you acces the int returns. 

良好做法,如果一個方法具有不同的返回另一方面,它們必須有不同的名稱。

0

因爲

 public string myFunc(int a, int b) 

hiding

 public int myFunc(int a, int b)