如何使用派生类变量?基类变量正在自动使用

时间:2019-04-19 07:41:16

标签: c# inheritance

我继承了Kingdom类的Plant和Animal类以及Animal类的Mammalia类。

我在所有类别中创建了布尔变量fly,milk和fruit,这些类别根据类别进行了不同分配。

王国中有一些方法可以检查果蝇,牛奶和水果,并相应地提供输出。这些方法被所有类继承。

但是,当我使用植物和哺乳动物的对象来使用继承的方法时,将使用Kingdom类变量而不是预期的类变量。

代码有点长。抱歉。

class Kingdom
{
    private bool milk, wings, fruits;

    public Kingdom() : this(true, true, true) {}
    public Kingdom(bool m, bool w, bool f)
    {
        milk = m;
        wings = w;
        fruits = f;
    }

    public virtual string me()
    {
        return "Kingdom Member";
    }

    public virtual void Fly()
    {
        if(this.wings)
        {
            Console.WriteLine(me() + " may Fly.");
        }
        else
        {
            Console.WriteLine(me() + " can not Fly.");
        }
    }

    public virtual void Fruit()
    {
        if(this.fruits)
        {
            Console.WriteLine(me() + " may bear Fruits.");
        }
        else
        {
            Console.WriteLine(me() + " can not bear Fruits.");
        }
    }

    public virtual void Milk()
    {
        if(this.milk)
        {
            Console.WriteLine(me() + " may produce milk.");
        }
        else
        {
            Console.WriteLine(me() + " can not produce milk.");
        }
    }
}

class Plant : Kingdom
{
    private bool milk, wings, fruits;

    public Plant()
    {
        milk = false;
        wings = false;
        fruits = true;
    }

    public override string me()
    {
        return "Plants";
    }
}

class Animelia : Kingdom
{
    private bool milk, wings, fruits;

    public Animelia()
    {
        milk = true;
        wings = true;
        fruits = false;
    }

    public override string me()
    {
        return "Animals";
    }
}

class Mamalia : Animelia
{
    private bool milk, wings, fruits;

    public Mamalia()
    {
        milk = true;
        wings = false;
        fruits = false;
    }

    public override string me()
    {
        return "Mamals";
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!\nLets learn Basic Kingdoms.\n");

        Kingdom p1 = new Plant();
        Kingdom m1 = new Mamalia();

        p1.Fly();
        p1.Milk();
        p1.Fruit();
        Console.WriteLine();
        m1.Fly();
        m1.Milk();
        m1.Fruit();
    }
}

这些是我担心的警告:

Program.cs(80,35):警告CS0414:已分配字段“ Animelia.fruits”,但从未使用过其值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

Program.cs(80,28):警告CS0414:分配了字段'Animelia.wings',但从未使用过其值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

Program.cs(97,28):警告CS0414:已分配字段'Mamalia.wings',但从未使用过其值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

Program.cs(63,28):警告CS0414:已分配字段“ Plant.wings”,但从未使用过其值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

Program.cs(97,35):警告CS0414:已分配字段“ Mamalia.fruits”,但从未使用过其值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

Program.cs(63,22):警告CS0414:已分配字段'Plant.milk',但从未使用过其值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

Program.cs(63,35):警告CS0414:已分配字段'Plant.fruits',但从未使用过其值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

Program.cs(80,22):警告CS0414:分配了字段'Animelia.milk',但从未使用过它的值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

Program.cs(97,22):警告CS0414:已分配字段“ Mamalia.milk”,但从未使用过其值[E:\ VS Code Programms \ C#\ Assignment \ Q5 \ Q5.csproj]

3 个答案:

答案 0 :(得分:1)

请从每个子类中删除milkwingsfruits字段。它们已经被继承。您要再次声明它们,从而将它们隐藏在Kingdom类中。

基本上,这意味着您要在此处设置的字段...

public Plant()
{
    milk = false;
    wings = false;
    fruits = true;
}

Kingdom中的不同。因此,Kingdom中的方法不知道您创建的这些新字段。

删除字段声明后,milkwingsfruits将引用Kingdom类中声明的字段。

您的代码应如下所示:

class Plant : Kingdom
{

    public Plant()
    {
        milk = false;
        wings = false;
        fruits = true;
    }

    public override string me()
    {
        return "Plants";
    }
}

class Animelia : Kingdom
{
    public Animelia()
    {
        milk = true;
        wings = true;
        fruits = false;
    }

    public override string me()
    {
        return "Animals";
    }
}

class Mamalia : Animelia
{
    public Mamalia()
    {
        milk = true;
        wings = false;
        fruits = false;
    }

    public override string me()
    {
        return "Mamals";
    }
}

此外,我认为您的课程之间的关系有点奇怪。 AnimalPlant是王国的示例,因此它们应该是Kingdom的实例,而不是从中继承。 Mammalia根本不是Kingdom。王国是古细菌,真细菌,原生生物,真菌,植物和动物界。

答案 1 :(得分:1)

您不需要在派生类中定义milkwingsfruit变量,因为它们已经存在于基类中。

要在派生类中设置这些变量,您已经有一个构造函数,可以在这里执行此操作:

public Kingdom(bool m, bool w, bool f)
{
    milk = m;
    wings = w;
    fruits = f;
}

您需要做的就是使用base关键字在基类中使用该构造函数。例如:

class Plant : Kingdom
{    
    public Plant() : base(false, false, true)
    {
    }

    public override string me()
    {
        return "Plants";
    }
}

答案 2 :(得分:1)

Fly(),Milk()和Fruit()方法在基本Kingdom类的上下文中运行,并且正在访问该类中的本地私有类变量。

问题在于,Kingdom类无法直接访问子类中变量的重新定义版本,因此为什么会收到未使用它们的错误。

正如其他人所说,理想情况下,您实际上不会在每个子类中重新定义变量,而是将Kingdom中的变量设置为“受保护”而不是“私有”。然后,您将能够在每个子类的构造函数中直接设置这些变量。但是,要解决您的为什么问题,您会收到警告,提示未使用每个子类中的变量,请继续阅读...

解决此问题的一种方法是在Kingdom类中添加一些虚拟的Get访问器方法,然后可以在子类中对其进行重写,以读取变量的本地重新定义版本。

请注意:我在这里使用了lamda“表达式绑定方法”语法,因为它使GetWings(),GetMilk()和GetFruit()方法变得美观而紧凑。如果愿意,可以将它们扩展为健全的方法。

class Kingdom
{
    private bool milk, wings, fruits;

    public Kingdom() : this(true, true, true) { }
    public Kingdom(bool m, bool w, bool f)
    {
        milk = m;
        wings = w;
        fruits = f;
    }

    public virtual string me()
    {
        return "Kingdom Member";
    }

    protected virtual bool GetMilk() => milk;
    protected virtual bool GetWings() => wings;
    protected virtual bool GetFruits() => fruits;

    public virtual void Fly()
    {
        if (GetWings())
        {
            Console.WriteLine(me() + " may Fly.");
        }
        else
        {
            Console.WriteLine(me() + " can not Fly.");
        }
    }

    public virtual void Fruit()
    {
        if (GetFruits())
        {
            Console.WriteLine(me() + " may bear Fruits.");
        }
        else
        {
            Console.WriteLine(me() + " can not bear Fruits.");
        }
    }

    public virtual void Milk()
    {
        if (GetMilk())
        {
            Console.WriteLine(me() + " may produce milk.");
        }
        else
        {
            Console.WriteLine(me() + " can not produce milk.");
        }
    }
}

class Plant : Kingdom
{
    private bool milk, wings, fruits;

    public Plant()
    {
        milk = false;
        wings = false;
        fruits = true;
    }

    public override string me()
    {
        return "Plants";
    }

    protected override bool GetMilk() => milk;
    protected override bool GetWings() => wings;
    protected override bool GetFruits() => fruits;
}

class Animelia : Kingdom
{
    private bool milk, wings, fruits;

    public Animelia()
    {
        milk = true;
        wings = true;
        fruits = false;
    }

    public override string me()
    {
        return "Animals";
    }

    protected override bool GetMilk() => milk;
    protected override bool GetWings() => wings;
    protected override bool GetFruits() => fruits;
}

class Mamalia : Animelia
{
    private bool milk, wings, fruits;

    public Mamalia()
    {
        milk = true;
        wings = false;
        fruits = false;
    }

    public override string me()
    {
        return "Mamals";
    }

    protected override bool GetMilk() => milk;
    protected override bool GetWings() => wings;
    protected override bool GetFruits() => fruits;
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!\nLets learn Basic Kingdoms.\n");

        Kingdom p1 = new Plant();
        Kingdom m1 = new Mamalia();

        p1.Fly();
        p1.Milk();
        p1.Fruit();
        Console.WriteLine();
        m1.Fly();
        m1.Milk();
        m1.Fruit();
    }
}

使用上述修改后的代码,我得到了以下结果:

Hello World!
Lets learn Basic Kingdoms.

Plants can not Fly.
Plants can not produce milk.
Plants may bear Fruits.

Mamals can not Fly.
Mamals may produce milk.
Mamals can not bear Fruits.