Помощь с переопределением и наследованием - PullRequest
23 голосов
/ 03 декабря 2008

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

Я не могу понять, почему я не могу переопределить метод из родительского класса. Вот код из базового класса (да, я украл код 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();
        }
    }
}

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

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

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

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

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

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

Ответы [ 8 ]

61 голосов
/ 03 декабря 2008

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

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

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

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

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

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

  protected sealed override string GetMood() {...}
7 голосов
/ 03 декабря 2008

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

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

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

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

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

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

5 голосов
/ 03 декабря 2008

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

3 голосов
/ 03 декабря 2008

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

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

    //...
}

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

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

Моя программа.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.");
        }
    }
}
2 голосов
/ 03 декабря 2008

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

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

public class SadObject: MoodyObject    
{        
    override String getMood()
2 голосов
/ 03 декабря 2008

Сделав ваш метод 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 # (как указано Dan C.)

1 голос
/ 03 декабря 2008
public class SadObject: MoodyObject
    {
        override String getMood()
0 голосов
/ 03 декабря 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...