Скрыть реализацию виртуального метода, если перегруженный метод присутствует в конкретной реализации - PullRequest
0 голосов
/ 12 ноября 2010

Вот ситуация. У меня есть базовый класс, который реализует метод, который принимает строку и устанавливает свойство в значение этой строки. Под этим у меня есть группа конкретных классов, которые реализуют базу. Некоторые из конкретных классов могут принимать любое строковое значение для хранения. Однако некоторые значения класса ограничены в пределах ряда значений Enumerated. Конечное значение по-прежнему является строкой, но оно должно находиться в пределах перечисляемого набора возможных значений.

Вот что я хотел бы сделать: Для классов, которые используют ограниченное перечислением значение, я хочу реализовать перегрузку для строкового метода, который вызывает строковый метод с правильным значением. Однако я также хочу заблокировать реализацию строки, чтобы можно было использовать только реализацию перечисления для передачи нового значения, чтобы обеспечить ограничение перечисления.

На данный момент я знаю, что этого просто не произойдет с помощью переопределения или нового в объявлении метода. Я также знаю, что мог бы создать иерархию, подобную Base -> [BaseString | BaseEnum] -> Concrete, и использовать герметизацию, чтобы не дать конкретной реализации использовать строковую реализацию. Я хотел бы знать, есть ли другой способ сделать это, который пропускает дополнительный уровень иерархии и позволяет мне просто сказать: «Если перегрузка метода присутствует в конкретном классе, заблокируйте метод».

public class Abstract {
    public virtual string ValueHolder { get; private/protected set; }
    public virtual void DoSomething( string s ) { ...; }
}

public class ConcreteEnum : Abstract {
    public void DoSomething( Enum e ) { 
        base.DoSomething( "String somehow extracted from enum");
    }
}

public class ConcreteString : Abstract { ... }

public class Main {
    ConcreteString sc = new ConcreteString();
    ConcreteEnum se = new ConcreteEnum();

    sc.DoSomething( "I don't have an overload defined, 
        so I'm using my base's string handler method.  
        I can be any value, I have no restrictions." );

    se.DoSomething( SomeEnum.MyValueWillBeRunThroughTheBaseStringHandler );
    se.DoSomething( "I don't work because there's an
        overload defined in my concrete class, and my
        value is restricted to a specific set of
        possibilities." );
}

Как я уже сказал, я знаю, что есть другие жизнеспособные способы сделать это, я просто хочу знать, возможно ли это / более чисто, чем эти альтернативы.

1 Ответ

2 голосов
/ 12 ноября 2010

В основном вам нужно просто проверить строку в производном классе:

public class ConcreteEnum : Abstract {
    public void DoSomething( Enum e ) { 
        base.DoSomething( "String somehow extracted from enum");
    }

    public override void DoSomething( string s ) {
        // Validate s, then do something with it
    }
}

Вы не можете полностью удалить метод, поскольку он является членом суперкласса и, следовательно, частью интерфейса класса.,Например, если вы передали экземпляр ConcreteEnum методу, который принимает объект Abstract и ожидал, что метод DoSomething(string) сработает, но он волшебным образом исчез, весь ад исчезнет.

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

РЕДАКТИРОВАТЬ: Если метод базового класса DoSomething не предполагается использовать, кроме как в подклассах (не говоря это,но вы на самом деле не указали ни того, ни другого), почему бы просто не сделать это protected?

...