Вопрос

Хорошо, терпите меня, ребята и девочки, пока я учусь.Вот мой вопрос.

Я не могу понять, почему я не могу переопределить метод родительского класса.Вот код базового класса (да, я украл код Java из книги ООП и пытаюсь переписать его на C#).

using System;

public class MoodyObject
{
    protected String getMood()
    {
        return "moody";
    }

    public void queryMood()
    {
        Console.WriteLine("I feel " + getMood() + " today!");
    }
}

и вот еще два моих объекта, которые наследуют базовый класс (MoodyObject):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class SadObject: MoodyObject
    {
        protected String getMood()
        {
            return "sad";
        }

        //specialization
        public void cry()
        {
            Console.WriteLine("wah...boohoo");
        }
    }
}

И:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class HappyObject: MoodyObject
    {
        protected String getMood()
        {
            return "happy";
        }

        public void laugh()
        {
            Console.WriteLine("hehehehehehe.");
        }
    }
}

и вот мое основное:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MoodyObject moodyObject = new MoodyObject();
            SadObject sadObject = new SadObject();
            HappyObject happyObject = new HappyObject();

            Console.WriteLine("How does the moody object feel today?");
            moodyObject.queryMood();
            Console.WriteLine("");
            Console.WriteLine("How does the sad object feel today?");
            sadObject.queryMood();
            sadObject.cry();
            Console.WriteLine("");
            Console.WriteLine("How does the happy object feel today?");
            happyObject.queryMood();
            happyObject.laugh();
        }
    }
}

Как видите, довольно простые вещи, но вот результат:

Что чувствует сегодня капризный объект?У меня сегодня настроение!

Как грустный объект чувствует себя сегодня?Я Почувствуй настроение сегодня!вау... ууууу

Что чувствует счастливый объект сегодня?У меня сегодня настроение!хехехехехехе.Нажмите любую клавишу для продолжения ...

Не так, как я ожидал.Я попытался сделать базовый метод виртуальным и вызвать переопределение при попытке его переопределить, и это просто привело к ошибке: «Невозможно переопределить унаследованный член MoodyObject.getMood()», поскольку он не помечен как виртуальный, абстрактный или переопределенный».Я также попробовал это без виртуального и переопределения, и он думает, что я пытаюсь скрыть базовый метод.Опять же, я новичок в ООП и буду признателен за любые рекомендации.

ОТРЕДАКТИРОВАНО, ЧТОБЫ ДОБАВИТЬ:Я нашел это!MoodyObject.cs был всего лишь «элементом решения» в обозревателе решений, а не элементом «ConsoleApplication1».Я перетащил его туда, где ему было место в обозревателе решений, и вуаля!Теперь это работает.Я отметил ответ Люка ниже как ответ, потому что он предложил мне необходимую помощь, чтобы добраться до того места, где я решил проблему...Я многому учусь здесь.Это потрясающе, а вы, ребята и девочки, безумно умные!

Это было полезно?

Решение

В C# методы по умолчанию не являются виртуальными, поэтому, если вы проектируете какой-либо метод как переопределяемый, вам следует указать его как виртуальный:

class Base 
{
  protected virtual string GetMood() {...}
}

Во-вторых, вам необходимо указать, что вы собираетесь переопределить метод базового класса в производном классе.

class Derived : Base
{
  protected override string GetMood() {...}
}

Если вы не укажете ключевое слово «переопределить», вы получите метод, который скрывает базовый тип (и предупреждение от компилятора о необходимости использования ключевого слова «новое» для метода, чтобы явно указать это).

Если вы хотите остановить цепочку наследования и запретить дальнейшие переопределения метода, вам следует пометить метод как запечатанный, например:

  protected sealed override string GetMood() {...}

Другие советы

Вам необходимо использовать ключевое слово override, чтобы переопределить любые виртуальные или реализовать любые абстрактные методы.

public class MoodyObject
{
    protected virtual String getMood() 
    { 
        return "moody"; 
    }    
    public void queryMood() 
    { 
        Console.WriteLine("I feel " + getMood() + " today!"); 
    }
}

public class HappyObject : MoodyObject
{
    protected override string getMood()
    {
        return "happy";
    }
}

Я бы порекомендовал здесь то, что вы, вероятно, хотели, чтобы MoodyObject был абстрактным классом.(Если вы сделаете это, вам придется изменить свой основной метод, но вам следует его изучить.) Действительно ли имеет смысл находиться в угрюмом режиме?Проблема с тем, что мы имеем выше, заключается в том, что ваш HappyObject не обязан предоставлять реализацию getMood. Создавая абстракцию класса, он делает несколько вещей:

  1. Вы не можете создать новый экземпляр абстрактного класса.Вам нужно использовать дочерний класс.
  2. Вы можете заставить производных дочерних элементов реализовать определенные методы.

Итак, чтобы сделать это, вы в конечном итоге:

public abstract class MoodyObject
{
    protected abstract String getMood();

    public void queryMood() 
    { 
        Console.WriteLine("I feel " + getMood() + " today!"); 
    }
}

Обратите внимание, что вы больше не предоставляете реализацию getMood.

Насколько я знаю, в Java все методы по умолчанию виртуальные.В C# это не так, поэтому вам необходимо пометить методы базового класса как «виртуальные», например protected virtual string getMood() ... и переопределения с помощью «переопределить», например. protected override string getMood()....

Если вы хотите переопределить метод базового класса, его необходимо объявить как virtual.Переопределяющий метод в производном классе должен быть явно объявлен как override.Это должно работать:

public class BaseObject
{
    protected virtual String getMood()
    {
        return "Base mood";
    }

    //...
}

public class DerivedObject: BaseObject
{
    protected override String getMood()
    {
        return "Derived mood";
    }
    //...
}

Редактировать: Я только что попробовал это в консольном приложении С#, и оно компилируется.Таким образом, исходный код, который вы используете, должен отличаться каким-то крошечным, но важным фрагментом от того, что вы разместили здесь.

Моя программа.cs это:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {    
            // leaving out your implementation to save space...    
        }
    }    

    public class SadObject : MoodyObject
    {
        protected override String getMood()
        {
            return "sad";
        }

        //specialization
        public void cry()
        {
            Console.WriteLine("wah...boohoo");
        }
    }

    public class HappyObject : MoodyObject
    {
        protected override String getMood()
        {
            return "happy";
        }

        public void laugh()
        {
            Console.WriteLine("hehehehehehe.");
        }
    }
}

Вам нужно сообщить C#, что ваш объект переопределяет функцию базового класса.

Вот статья MSDN о нужном вам синтаксисе: http://msdn.microsoft.com/en-us/library/ebca9ah3(VS.71).aspx

public class SadObject: MoodyObject    
{        
    override String getMood()

Сделав свой метод GetMood virtual в Муди и override в производных классах ваш код должен работать.Вы уверены, что разместили эти ключевые слова там, где они должны быть?Вот полный код, который отлично компилируется и работает:

public class MoodyObject
{
    protected virtual String getMood()
    {
        return "moody";
    }

    public void queryMood()
    {
        Console.WriteLine("I feel " + getMood() + " today!");
    }
}

public class SadObject : MoodyObject
{
    protected override String getMood()
    {
        return "sad";
    }

    //specialization
    public void cry()
    {
        Console.WriteLine("wah...boohoo");
    }
}

public class HappyObject : MoodyObject
{
    protected override String getMood()
    {
        return "happy";
    }

    public void laugh()
    {
        Console.WriteLine("hehehehehehe.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        MoodyObject moodyObject = new MoodyObject();
        SadObject sadObject = new SadObject();
        HappyObject happyObject = new HappyObject();

        Console.WriteLine("How does the moody object feel today?");
        moodyObject.queryMood();
        Console.WriteLine("");
        Console.WriteLine("How does the sad object feel today?");
        sadObject.queryMood();
        sadObject.cry();
        Console.WriteLine("");
        Console.WriteLine("How does the happy object feel today?");
        happyObject.queryMood();
        happyObject.laugh();

        Console.Read();
    }
}

Возможно, ваша ошибка связана с тем, что в Java все методы являются виртуальными, чего не происходит в C# (как отметил Дэн С.).

public class SadObject: MoodyObject
    {
        override String getMood()

Вам необходимо пометить переопределения getMood ключевым словом «override».Вам также необходимо пометить базовый метод getMood ключевым словом «virtual».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top