2014-05-16 66 views
-5

在C#中,我有一個有公共成員的父類。我想得出的父類,然後派生類中的公共成員,從而爲創建和訪問新方法,如下...爲什麼我無法訪問特定於我的子類的方法?

public class Animal { } 
    public class Sheep : Animal { 
     public void makeALamb() { } 
    } 
    public class Farm 
    { 
     public Animal myAnimal; 
    } 
    public class SheepFarm : Farm { 
     public void SheepFarm() { 
      this.myAnimal = new Sheep(); 
      this.myAnimal.makeALamb(); 
     } 
    } 

此代碼不能編譯。 「動物不包含makeALamb()的定義」。但是我想要做的是多態的本質,不是嗎?我錯過了什麼?我非常期待找到答案。

提前致謝!

回答

1

如果我猜正確你打算做什麼,可以考慮使用泛型:

public class Farm<TAnimal> where TAnimal : Animal 
{ 
    public TAnimal myAnimal; 
} 

public class SheepFarm : Farm<Sheep> 
{ 
    public void SheepFarm() 
    { 
     this.myAnimal = new Sheep(); 
     this.myAnimal.makeALamb(); 
    } 
} 
0

makeALamb()Sheep的方法,而不是AnimalSheep來自Animal,而不是其他方式。

9

因爲myAnimal的類型是Animal。因此,它只能訪問Animal的成員...和Animal沒有方法makeALamb

這裏作業的右手邊:

this.myAnimal = new Sheep(); 

..says它是什麼。左側說明你的代碼認爲它是什麼。在你的任務左側是:

public Animal myAnimal; 
//  ^^^^^^ 

現在..假裝你已經嘗試過什麼是可能的..可以這樣考慮:

this.myAnimal = new Snake(); 
this.myAnimal.makeALamb(); // what does it call here? 

this.myAnimal = new Giraffe(); 
this.myAnimal.makeALamb(); // what here? 

當你調用makeALamb應該發生..what一個Snake實例? ...

0

this.myAnimal定義爲作爲AnimalAnimal沒有makeALamb方法。既然你一個Sheepthis.myAnimal,你可以它:

((Sheep)this.myAnimal).makeALamb(); 

這有效地表示:「就拿this.myAnimal,治療是作爲Sheep並在其上調用makeALamb()」。如果this.myAnimal不是確實 a在運行時會出現異常。

0

如果您想訪問makeALamb方法,您必須將您的Animal實例投射到Sheep

public void SheepFarm() 
{ 
    this.myAnimal = new Sheep(); 
    ((Sheep)this.myAnimal).makeALamb(); 
} 

沒有鑄造myAnimal被認爲是類型的Animal,因此,你只能訪問的Animal成員和的Animal基類(ES)的成員(其中不存在基類OLF Animal在這種情況下)。

另一方面,當然這不是訪問類成員的優雅和安全的方式。如果您想通過基類實例訪問一些常見成員,那麼您應該在基類中聲明該成員(可能爲抽象虛擬),然後在派生類中實現(或覆蓋)它們。

+2

是的,但是這有點兒失敗的目的..向下轉換隻是訪問的東西.. ickypants。 –

+1

我可能會顯示OP如何安全地用'as'投射..因爲你現在已經打開了一堆蠕蟲的OP只是隨機啓動向下轉換到派生類......它可能不會成功:( –

0

的想法是,你的動物可以被實例化爲羊,但只能定義在該部件上它會處理動物。它是如此簡單:羊是動物,但動物不是羊,所以動物不能讓阿拉姆():)

0

你還沒有很好地定義農場類。這裏是例子:

public class Animal { } 
    public class Sheep : Animal { 
     public void makeALamb() { } 
    } 
public class Goat: Animal { 
     public void makeAGoat() { } 
    } 
    public class Farm 
    { 
     public Goat myGoat; 
     public Sheep mySheep; 
    } 
    public class MyFarm : Farm { 
     public void MyFarm() { 
      this.mySheep= new Animal(); 
      this.mySheep.makeALamb(); 
     } 
    } 

每隻動物不是山羊,但每隻山羊都是動物。

0

因爲,要使用多態,更改您的代碼:

public abstract class Animal 
{ 
    public abstract void makeChild(); 
} 

public class Sheep : Animal 
{ 
    public override void makeChild() 
    { 
     Console.WriteLine("A lamb is born."); 
    } 
} 

public class Cow : Animal 
{ 
    public override void makeChild() 
    { 
     Console.WriteLine("A calf is born."); 
    } 
} 

public class Farm 
{ 
    public Animal myAnimal; 
} 

public class SheepFarm : Farm 
{ 
    public SheepFarm() 
    { 
     this.myAnimal = new Sheep(); 
     this.myAnimal.makeChild(); 
    } 
} 

public class CowFarm : Farm 
{ 
    public CowFarm() 
    { 
     this.myAnimal = new Cow(); 
     this.myAnimal.makeChild(); 
    } 
} 

,並使用下面的 「主要()」 方法:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Farm sf = new SheepFarm(); 
     Farm cf = new CowFarm(); 
    } 
} 

不過,我應該指向這不是一個好的用例場景。多態性的一個更好的和更簡單的使用情況是擺脫農場類,並使用以下「的Main()」方法,而不是以前的一個:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Animal[] animals = { 
      new Sheep(), 
      new Cow(), 
      new Sheep(), 
      new Cow(), 
      new Cow() 
     }; 

     foreach (Animal animal in animals) 
     { 
      animal.makeChild(); 
     } 
    } 
} 
相關問題