Here's the situation. I have a base class which implements a method that accepts a string, and sets a property to the value of that string. Under that, I have a group of concrete classes that implement the base. Some of the concrete classes can accept any string value to be stored. However, some of the class's values are constrained within an Enumerated series of values. The final value is still a string, but the value must be within that enumerated set of possible values.
Here's what I'd like to do: For the classes which use an enum-restricted value, I want to implement an overload to the string method that开发者_运维问答 calls the string method with the correct value. However, I also want to lock the string implementation out so that only the enum implementation can be used to pass a new value in, in order to enforce the enum restriction.
I know at this point that this just isn't going to happen through the use of override or new in the method declaration. I also know that I could create a hierarchy like Base -> [BaseString|BaseEnum] -> Concrete and use sealing to keep the concrete implementation from allowing the string-based implementation to be used. What I'd like to know is if there's another way to do this that skips the extra level of hierarchy and allows me to just say "If method overload is present in concrete class, lock method."
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." );
}
As I said, I know that there are other viable ways of doing this, I just want to know if this is possible/more clean than those alternatives.
You would basically need to just validate the string in the derived class:
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
}
}
You can't remove the method entirely, since it is a member of the superclass and hence part of the class interface. For example, if you passed an instance of ConcreteEnum
to a method that takes an Abstract
object and expected the DoSomething(string)
method to work, but it was magically gone, all hell would break loose.
But you always have the option of overriding the behavior in a subclass to throw exceptions when an invalid value is supplied. You could even override it to just throw a NotSupportedException
.
EDIT: If the base class DoSomething
method is not supposed to be consumed except in subclasses (not saying it is, but you didn't really specify either way), why not just make it protected
?
精彩评论