为什么我无法访问特定于我的子类的方法?

时间:2014-05-16 14:16:02

标签: c# object polymorphism

在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();
        }
    }

此代码无法编译。 “Animal不包含makeALamb()的定义”。但我想做的是多态的本质,不是吗?我错过了什么?我非常期待找到答案。

提前致谢!

8 个答案:

答案 0 :(得分:8)

因为myAnimal的类型为Animal。因此,它只能访问Animal的成员...而Animal没有方法makeALamb

这里任务的右侧:

this.myAnimal = new Sheep();

..说出它是什么。左侧显示您的代码所看到的内容。作业的左侧是:

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个实例上调用Snake时会发生什么? ......

答案 1 :(得分: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();
    }
}

答案 2 :(得分:0)

makeALamb()Sheep的方法,而非AnimalSheep来自Animal,而不是相反。

答案 3 :(得分:0)

this.myAnimal 已定义AnimalAnimal没有makeALamb方法。由于您Sheep放在this.myAnimal中,

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

这实际上说:&#34;接受this.myAnimal,视为Sheep并在其上调用makeALamb()&#34;。如果this.myAnimal在运行时不是真的一只羊,那么您将获得例外。

答案 4 :(得分:0)

如果您想要访问Animal方法,则必须将Sheep实例投射到makeALamb

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

没有强制转换myAnimal被视为Animal的类型,因此您只能访问Animal的成员和Animal的基类成员(在这种情况下没有基类olf Animal。)

另一方面,当然,这不是访问类成员的优雅而安全的方法。如果您想通过基类实例访问某些公共成员,那么您应该在基类中声明成员(可能是 abstract virtual ),然后在派生类中实现(或覆盖)它们。

答案 5 :(得分:0)

这个想法是你的Animal可以被实例化为Sheep,但它只会处理Animal上定义的成员。它很简单:绵羊是一种动物,但动物不是绵羊,所以动物不能制作Alpha():)

答案 6 :(得分:0)

您还没有很好地定义Farm类。这是一个例子:

 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();
        }
    }

每只动物都不是山羊,但每只山羊都是动物。

答案 7 :(得分: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();
    }
}

并使用以下&#34; Main()&#34;方法:

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

但是,我应该指出,这不是一个好的用例场景。一个更好更简单的多态性用例是摆脱Farm类并使用以下&#34; Main()&#34;方法而不是前一个方法:

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();
        }
    }
}
相关问题