Есть ли явное объявление интерфейса для абстрактных методов? - PullRequest
2 голосов
/ 12 апреля 2011

У меня есть (довольно простая) проблема, и кажется, я не могу понять, как это сделать.Я был бы признателен за помощь.

У меня есть два класса, которые похожи на это:

public class FileParameters { ... }

public abstract class File {
    ...
    public abstract FileParameters Params { get; }
}

Из обоих классов у меня есть производная специальная версия:

public class SpecialFileParameters { ... }

public abstract class SpecialFile {
    ...
    private SpecialFileParameters params;
    public override FileParameters Params { get { return params; } }
}

Когда я хочу использовать SpecialFileParameters, я должен сначала привести их, например:

((SpecialFileParameters)SpecialFileObject.Parameters).DoSomething();

, что довольно неприятно.То, что я хотел бы иметь, это в основном тот же синтаксис, что и для интерфейсов

public abstract class SpecialFile {
    ...
    private SpecialFileParameters params;
    private override FileParameters File.Params { get { return params; } }
    public new SpecialFileParameters Params { get { return params; } }
}

Но вот так я получаю ошибку компилятора: «Файл» в явном объявлении интерфейса не является интерфейсом.Есть ли другой способ сделать это?

Дополнительная информация:

  • Я не могу изменить базовые классы, только мои специальные классы
  • Мне действительно нужны 2 специальныхпроизводные классы, один написан на C #, другой на C ++ / CLI.Если "хитрость" в том, чтобы заставить его работать, отличается в C # и C ++ CLI, пожалуйста, дайте мне знать.

Спасибо за вашу помощь (и терпение, я думаю, ^^),

Ответы [ 4 ]

2 голосов
/ 13 апреля 2011

В C ++ / CLI это несколько отличается, пример явного переопределения:

public ref struct BaseClass abstract
{
    virtual int Func(int) abstract;
};

public ref struct DerivedClass : BaseClass
{
    virtual int BaseFunc(int x) = BaseClass::Func { return x + 2; }
    virtual int Func(int y) new { return y / 2; }
};

int main(array<System::String ^> ^args)
{
    DerivedClass^ d = gcnew DerivedClass();
    BaseClass^ b = d;
    System::Console::WriteLine("4 ->  Base   -> " + b->Func(4));
    System::Console::WriteLine("4 -> Derived -> " + d->Func(4));

    return 0;
}

Марк показал, что вам нужно сделать для C #: используйте дополнительный уровень наследования.

1 голос
/ 12 апреля 2011

Нет, в C # нет синтаксиса для обозначения явного абстрактного метода переопределения (в отличие от другого метода с такой же сигнатурой), и, поскольку вы не можете иметь две совпадающие сигнатуры, объявленные на одном уровне, вы не можете сделать это вполнечто вы хотите.

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

public abstract class File {
    public abstract FileParameters Params { get; }
}
public abstract class FileIntermediate : File
{
    public override FileParameters Params {get { return ParamsImpl; }}
    protected abstract FileParameters ParamsImpl { get; }
}
public class SpecialFile : FileIntermediate
{
    public new SpecialFileParameters Params { get { return null; } }// TODO 
    protected override FileParameters ParamsImpl {get { return Params; }}
}
0 голосов
/ 12 апреля 2011

Необходимо ли иметь одинаковое имя метода между двумя методами (переопределение и новый метод)? В этих ситуациях я обычно создаю новый метод с новым именем, который возвращает более производный тип, а затем переопределяю вызов этого метода в его реализации:

public override FileParameters Params { get { return SpecialParams; } }     
public SpecialFileParameters SpecialParams { get { return params; } } 

Таким образом, когда у вас есть объект SpecialFile, вам не нужно приведение. Если это не работает, возможно, вы могли бы объяснить больше, почему вам нужно, чтобы имена методов были одинаковыми для вашей ситуации.

0 голосов
/ 12 апреля 2011

Вы можете использовать дженерики для решения этой проблемы:

    public class FileParameters   {    }

    public class SpecialFileParameters : FileParameters{}

    public abstract class File<T>
        where T : FileParameters
    {
        private T _params;

        public T Params   { get { return _params;}        }
    }

    public class SpecialFileParams : FileParameters<SpecialFileParameters> { }

, и вы получите конкретное «Специальное предложение» при доступе к параметрам.

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