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

С# частный (скрытый) базовый класс

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

Например:

using System.IO;

class BaseOutput: Stream           // Hidden base class
{
    protected BaseOutput(Stream o)
    { ... }

    ...lots of common methods...
}

public class MyOutput: BaseOutput  // Public subclass
{
    public BaseOutput(Stream o):
        base(o)
    { ... }

    public override int Write(int b)
    { ... }
}

Здесь я хотел бы, чтобы класс BaseOutput был недоступен для клиентов моей библиотеки, но разрешить публичный подкласс MyOutput. Я знаю, что С# не позволяет базовым классам иметь более ограничительный доступ, чем подклассы, но есть ли другой законный способ достижения такого же эффекта?

UPDATE

Мое решение для этой конкретной библиотеки состоит в том, чтобы сделать базовый класс public и abstract, и документировать его с помощью "Не использовать этот базовый класс напрямую". Я также создаю конструктор базового класса internal, который эффективно запрещает внешним клиентам использовать или наследовать класс.

(Это позор, потому что другие языки O-O позволяют мне иметь скрытые базовые классы.)

4b9b3361

Ответ 1

К сожалению, нет. Вы не можете вывести открытый класс из внутреннего или закрытого класса.

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

Ответ 2

Рассмотрим шаблон, такой как "Фасад". Это то, для чего они есть. Я не думаю, что вы можете достичь того, что вам нужно, с прямым наследованием.

Ответ 3

В зависимости от того, что делает "множество общих методов", вы можете достичь некоторых из них с помощью внутренних методов расширения:

internal static class MyStreamExtensions
{
   internal static int UsefulOne(this Stream stream)
   {
     return 42; 
   }
}   

Другим подходом является создание внутреннего конструктора для предотвращения непреднамеренного вывода из этого класса:

public class BaseOutput: Stream
{
    internal BaseOutput(Stream o)
    { ... }

    ...lots of common methods...
}

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