Подтвердить что ты не робот

Переопределение и наследование в С#

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

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

using System;

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

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

и вот мои другие 2 объекта, которые наследуют базовый класс (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();
        }
    }
}

Как вы можете видеть, довольно простой материал, но вот вывод:

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

Как чувствует себя грустный объект? я чувствую себя капризным сегодня! вах... громко рыдать или смеяться

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

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

EDITED TO ADD: Я нашел его! MoodyObject.cs был всего лишь "элементом решения" в проводнике решений, а не элементом "ConsoleApplication1". Я перетащил его туда, где он принадлежал исследователю решений и вуаля! Он работает сейчас. Я отметил Люк ниже, как ответ, потому что он предложил помощь, в которой я нуждался, чтобы добраться до того, где я ее разрешил... Я так много учусь здесь. Это потрясающе, и вы, ребята, и девочки сумасшедшие умные!

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

Вам нужно использовать ключевое слово 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. При создании абстрактного класса он выполняет несколько действий:

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

Для этого вам нужно:

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

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

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

Ответ 3

Насколько я знаю, в Java все методы по умолчанию являются виртуальными. Это не относится к С#, поэтому вам нужно пометить методы базового класса "виртуальными", например. protected virtual string getMood() ... и переопределения с "переопределением", например. protected override string getMood()....

Ответ 4

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

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

    //...
}

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

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

Моя program.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.");
        }
    }
}

Ответ 5

Создав свой метод GetMood virtual в Moody и 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.).

Ответ 6

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

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

public class SadObject: MoodyObject    
{        
    override String getMood()

Ответ 7

public class SadObject: MoodyObject
    {
        override String getMood()

Ответ 8

Вам нужно отметить переопределения getMood ключевым словом "override". Вам также нужно будет пометить базовый метод getMood с помощью "виртуального" ключевого слова.