Limit inheritance of intermediate abstract class - c#

I have an abstract class, CreatureBehaviour, that provides a TakeTurn method. The goal of this is to decide what the creature should do, and it should provide its response via callback. This is because the response may require player input, so it shouldn't block other processes.
public abstract class CreatureBehaviour {
public abstract void TakeTurn (Action<TurnAction> response);
}
Inheriting from this, the PlayerControl class stores the response callback for later decision-making. Most of its content isn't relevant, but ultimately it must invoke response when the player does something.
public class PlayerControl : CreatureBehaviour {
Action<TurnAction> responseCallback;
public override void TakeTurn(Action<TurnAction> response) {
responseCallback = response;
}
// Various UI callbacks that can send something to "responseCallback" when appropriate.
}
And all non-player creatures need to be able to send a callback too. For safety, I want to ensure that a callback is always hit, so I've created an abstract NonPlayerControl class that ensures a response:
public abstract class NonPlayerControl : CreatureBehaviour {
protected abstract TurnAction TurnResponse ();
public override void TakeTurn (Action<TurnAction> response) {
response (TurnResponse ());
}
}
With this, all of my non-player creature behaviours can derive from NonPlayerControl and simply implement TurnReponse(). The compiler guarantees that all their scripts will return a response, rather than leaving the callback hanging. Note that PlayerControl can't implement TurnResponse() because it would need to guarantee an immediate return, and that would block other processes.
So I want to derive other classes from NonPlayerControl and maybe from PlayerControl, but I don't want to accidentally derive another class from CreatureBehaviour and risk missing the callback.
Is there any way I can "sort of seal" CreatureBehaviour so that it can only have these two direct children and prevent any others? If not, is there a better pattern I could be using here?

There's nothing you could do for this in a "normal" way, but there's one option you could consider...
If you give your CreatureBehavior class just a private constructor, then nest PlayerBehavior and NonPlayerBehavior within that class, they will have access to the private constructor but no other classes will... so no other classes could derive from CreatureBehavior.
A simpler solution would be to:
Document in CreatureBehavior that it shouldn't be subclassed directly
Write unit tests to validate that there aren't any other subclasses
That can only test your code rather than code in other assemblies, of course. If you don't need these from other assemblies, then make the classes internal instead of public. Even if you need all the classes to be public, you could include a no-op abstract internal method that's implemented in PlayerBehavior and NonPlayerBehavior - that will stop classes outside your assembly from deriving from CreatureBehavior as they can't implement the internal abstract method.

Just a quick idea, without further testing: Could you use a generic to do the restriction?
public abstract class CreatureBehaviour<T> where T : IPlayerControl, INonPlayerControl {
// ...
}
And then use it in the following way:
public abstract class NonPlayerControl : CreatureBehaviour<NonPlayerControl>, INonPlayerControl {
// ...
}
public abstract class PlayerControl : CreatureBehaviour<PlayerControl>, IPlayerControl {
// ...
}
It is sort of a hack, but it might work for your case.

You cannot prohibit inheritance from the CreatureBehavoiur class but you can limit access to TakeTurn methods by combining internal, sealed and protected access and place it in the separate assembly:
public abstract class CreatureBehaviour
{
protected abstract void TakeTurn(Action<TurnAction> response);
}
public class PlayerControl : CreatureBehaviour
{
private Action<TurnAction> responseCallback;
protected override void TakeTurn(Action<TurnAction> response)
{
responseCallback = response;
}
internal void TurnByPlayer(Action<TurnAction> response)
{
TakeTurn(response);
}
// Various UI callbacks that can send something to "responseCallback" when appropriate.
}
public abstract class NonPlayerControl : CreatureBehaviour
{
protected abstract TurnAction TurnResponse();
protected override void TakeTurn(Action<TurnAction> response)
{
response(TurnResponse());
}
internal void TurnByNonPlayer(Action<TurnAction> response)
{
TakeTurn(response);
}
}
public sealed class CreatureStearing
{
public void Turn(PlayerControl control)
{
control.TurnByPlayer((action) => {});
}
public void Turn(NonPlayerControl control)
{
control.TurnByNonPlayer(action => {});
}
}
Now you can inherit from PlayerControl, NonPlayerControl, and even CreatureBehaviour in other assemblies, but you cannot use TakeTurn methods for any class intances other than PlayerControl and NonPlayerControl that are in separate assemblies:
public class SomeTest1 : PlayerControl
{
protected override void TakeTurn(Action<TurnAction> response)
{
base.TakeTurn(response);
}
}
public class SomeTest2 : NonPlayerControl
{
protected override TurnAction TurnResponse()
{
throw new NotImplementedException();
}
protected override void TakeTurn(Action<TurnAction> response)
{
base.TakeTurn(response);
}
}
public class SomeTest3 : CreatureBehaviour
{
protected override void TakeTurn(Action<TurnAction> response)
{
throw new NotImplementedException();
}
}
....
var t1 = new SomeTest1();
var t2 = new SomeTest2();
var t3 = new SomeTest3();
var creatureStearing = new CreatureStearing();
creatureStearing.Turn(t1);
creatureStearing.Turn(t2);
creatureStearing.Turn(t3); // 'Cannot resolve method 'compile error here
Of course you can pass this limitation by declaring internal access for your assembly, but it requires to implement something like CreatureStearing (well some efforts) but other party in this case will know for sure this is a hack.

Related

How to instantiate an extended class with a different base implementation?

I'm working with a binary that contains an object and the base class it extends. I want to instantiate the object, but for it to use my own implementation of the base class. I can see in the base class to know what methods I need t extend.
The problem is that the base class implements a method called "WriteFeed" that expects network connections and writes data out to a network stream. I would like it to use my implementation so WriteFeed can instead dump data to console.
I cannot change the existing binaries, only the way I consume and instantiate it.
My only suggestion is to use a composite approach. I'm not sure if this will meet your need or you have visibility access, but it may work.
public class SomeBaseClassInSomeBinary
{
protected virtual void Method1(...) {}
protected virtual void WriteFeed (...) {}
}
public class SomeClassInSomeBinary: SomeBaseClassInSomeBinary
{
protected override void Method1(...) { base.Method1(...); }
protected override void WriteFeed (...) { base.WriteFeed (...); }
}
// **** your code
public class MyCode: SomeBaseClassInSomeBinary
{
private SomeClassInSomeBinary Composite = new SomeClassInSomeBinary();
protected override void Method1(...) { Composite.Method1(...); }
protected override void WriteFeed (...) { your implementation }
}
}
All you need to do is now use your object instead.
Hope this helps.

Abstract class which concrete class to use? Design issue?

I have a design issue. I am modifying existing code and where I was instantiating new class. It's giving me errors due to turning the class into a Abstract class which I can understand. It's throwing an error because you can't create instances of abstract class.
I had this code below
ExampleProcessor pro = new ExampleProcessor();
but the ExmapleProcessor class is now turned into abstract class.
public abstract class ExmapleProcessor {
public abstract void Method1();
public abstract void Method2();
}
Child classes AExampleProcessor and BExampleProcessor.
public class AExampleProcessor : ExampleProcessor
{
public override void Method1() { //do something }
public override void Method2() { //do something }
}
public class BExampleProcessor : ExampleProcessor
{
public override void Method1() { //do something }
public override void Method2() { //do something }
}
So this line is causing 42 errors "ExampleProcessor pro = new ExampleProcessor();" everywhere in my application.
I dont want to do
AExampleProcessor pro = new AExampleProcessor();
and
BExampleProcessor pro = new BExampleProcessor();
because I want my application to decide which class to use. How can I make it so it loads up the correct class?
I would like code examples please..
Create a factory:
public static class ExampleProcessorFactory
{
public static ExampleProcessor Create()
{
if(IsFullmoon)
return new ExampleProcessorA();
else
return new ExampleProcessorB();
}
}
Then replace all calls to new ExampleProcessor() with calls to ExampleProcessorFactory.Create(). Now you've encapsulated the instantiation logic and the choosing of what concrete class to instantiate into one place where you can apply any logic to decide what class to instantiate. (The logic of deciding when to use which class might benefit from some improvement to be unrelated to the full moon.)
Since you want the application to decide which concrete subclass to use, I suggest you use a Factory pattern.
That way, the client code knows only that you are using an ExampleProcessor, and the implementation details remain hidden.

C# Overriding abstract methods (include input parameters)

It is possible in C# do something like this
public absctract class ImportBase()
{
public abstract void CreateDocument();
}
public class UsingOne : ImportBase
{
public override bool CreateDocument(string name)
{
return null;
}
}
I want have some Base class, which only have some methods,but in derived class i need change inputs parameters and inside of method.
You're not overriding the method. The point of having an abstract (or virtual) method is that given any ImportBase, I should be able to call
importBase.CreateDocument();
That's clearly not the case with UsingOne, as it needs more information. So you're really trying to tie your caller to UsingOne, not just ImportBase - at which point you've lost the benefits of polymorphism.
To override a method, the implementation has to have the same signature, basically.
Probably you want to minimize the duplicate code on your derived classes. Basically it's not possible to have an override of a different signature but surely you can refactor your code where you can keep the possible duplicate code in the base class and use it on your derived classes.
public absctract class ImportBase()
{
//Making this protected here
protected virtual void CreateDocument()
{
//Your CreateDocument code
};
}
public class UsingOne : ImportBase
{
private override void CreateDocument()
{
// Override this if you have different CreateDocument for your different
// for different derived class.
}
public bool CreateDocument(string name)
{
// Do whatever you need to do with name parameter.
base.CreateDocument();
// Do whatever you need to do with name parameter.
return true; // return false;
}
}
You can create instance of UsingOne and invoke CreateDocument(string name)
nope. signature must be same on the derived class. i suggest to use builder pattern.
http://en.wikipedia.org/wiki/Builder_pattern

What's the difference between an abstract class, and a class with only protected constructors? (.NET)

What are all the difference between an abstract class, and a class with only protected constructor(s)? They seem to be pretty similar to me, in that you can't instantiate either one.
EDIT:
How would you create an instance in a derived class, with a base class with a protected constructor? For instance:
public class ProtectedConstructor
{
protected ProtectedConstructor()
{
}
public static ProtectedConstructor GetInstance()
{
return new ProtectedConstructor(); // this is fine
}
}
public class DerivedClass : ProtectedConstructor
{
public void createInstance()
{
ProtectedConstructor p = new ProtectedConstructor(); // doesn't compile
}
public static ProtectedConstructor getInstance()
{
return new ProtectedConstructor(); // doesn't compile
}
}
You can instantiate a class with protected constructors from within the class itself - in a static constructor or static method. This can be used to implement a singleton, or a factory-type thing.
An abstract class cannot be instantiated at all - the intent is that one or more child classes will complete the implementation, and those classes will get instantiated
Edit:
if you call ProtectedConstructor.GetInstance(); instead of new ProtectedConstructor();, it works. Maybe protected constructors can't be called this way? But protected methods certainly can.
Here is an interesting article on the topic.
Most of the time, there is little practical difference, as both are only able to be generated via a subclass.
However, marking a class abstract has two benefits:
With protected constructors, it's still possible to create an instance of the class in two ways. You can use Activator.CreateInstance with BindingFlags.NonPublic, or you can use a factory method defined in the class (or a subclass) to create an instance of the class. A class marked abstract, however, cannot be created.
You are making your intention more clear by marking the class abstract. Personally, I find this the most compelling reason to do so.
From an outside , black-box perspective, yes they are similar in that you cannot instantiate either one. However, you can never instantiate an abstract class, where you can construct a class with only protected constructors from within the class itself, or from an inheritor.
An abstract class can have abstract methods; methods that consist only of the method signature, but no body, that child classes must implement.
Seriously, not one person mentioned that yet?
Your example is flawed because in the getInstance case because you construct a ProtectedConstructor class and expect to down cast it as a DerivedClass. Instead you need a slightly more complete implementation where the derived class has a constrcutor:
public class ProtectedConstructor
{
protected ProtectedConstructor(string arg)
{
// do something with arg
}
public static ProtectedConstructor GetInstance()
{
return new ProtectedConstructor("test");
}
}
public class DerivedClass : ProtectedConstructor
{
protected DerivedClass(string arg) : base(arg)
{
}
public void createInstance()
{
DerivedClass p = new DerivedClass("test");
}
public static DerivedClass getInstance()
{
return new DerivedClass("test");
}
}
Regardless the major difference usage of abstract classes is to define abstract methods that subclasses must implement but you don't want to provide a default implementation for. For example suppose you have some kind of Thread class that has a Run method. You want to ensure that every call to Run first setups up some logging then does the real work of the thread and then stops logging. You could write an abstract Thread class like this:
public abstract Thread
{
protected Thread()
{
}
public void Run()
{
LogStart();
DoRun();
LogEnd();
}
protected abstract DoRun();
private void LogStart()
{
Console.Write("Starting Thread Run");
}
private void LogEnd()
{
Console.Write("Ending Thread Run");
}
}
public class HelloWorldThread : Thread
{
public HelloWorldThread()
{
}
protected override DoRun()
{
Console.Write("Hello World");
}
}
Another thing to consider, that I didn't see other people mention, is that your code may be maintained in the future. If the maintainer adds a public constructor to a class, then it can be instantiated. This might break your design, so you should prevent it (or design to accommodate it).
To prevent other people from making these kinds of changes, you can comment your code. Or, as other people said, use "abstract" to explicitly document your intent.
Well, the first difference that comes to mind is that an abstract class can not be instantiated, but a class with protected constructors could be instantiated throw another public method.
A common example of this might be something like the Singleton pattern: http://en.wikipedia.org/wiki/Singleton_pattern
if you inherit an abstract class from another abstract class, you do not have to satisfy abstract methods, but you do with a normal class with protected ctors. Examples
public abstract class Parent
{
protected abstract void AMethod();
}
public abstract class Child: Parent
{
// does not implement AMethod, and that's ok
}
public class Child2: Parent
{
// does not implement AMethod, and that will cause a compile error
}
If your intent is to only allow static uses of the class (i.e. not to use it as a pure base class) then you should use the static keyword instead; the CLR will prevent instances of the class being created via any method including Reflection (AFAIK).

C# - using polymorphism in classes I didn't write

What is the best way to implement polymorphic behavior in classes that I can't modify? I currently have some code like:
if(obj is ClassA) {
// ...
} else if(obj is ClassB) {
// ...
} else if ...
The obvious answer is to add a virtual method to the base class, but unfortunately the code is in a different assembly and I can't modify it. Is there a better way to handle this than the ugly and slow code above?
Hmmm... seems more suited to Adapter.
public interface ITheInterfaceYouNeed
{
void DoWhatYouWant();
}
public class MyA : ITheInterfaceYouNeed
{
protected ClassA _actualA;
public MyA( ClassA actualA )
{
_actualA = actualA;
}
public void DoWhatYouWant()
{
_actualA.DoWhatADoes();
}
}
public class MyB : ITheInterfaceYouNeed
{
protected ClassB _actualB;
public MyB( ClassB actualB )
{
_actualB = actualB;
}
public void DoWhatYouWant()
{
_actualB.DoWhatBDoes();
}
}
Seems like a lot of code, but it will make the client code a lot closer to what you want. Plus it'll give you a chance to think about what interface you're actually using.
Check out the Visitor pattern. This lets you come close to adding virtual methods to a class without changing the class. You need to use an extension method with a dynamic cast if the base class you're working with doesn't have a Visit method. Here's some sample code:
public class Main
{
public static void Example()
{
Base a = new GirlChild();
var v = new Visitor();
a.Visit(v);
}
}
static class Ext
{
public static void Visit(this object b, Visitor v)
{
((dynamic)v).Visit((dynamic)b);
}
}
public class Visitor
{
public void Visit(Base b)
{
throw new NotImplementedException();
}
public void Visit(BoyChild b)
{
Console.WriteLine("It's a boy!");
}
public void Visit(GirlChild g)
{
Console.WriteLine("It's a girl!");
}
}
//Below this line are the classes you don't have to change.
public class Base
{
}
public class BoyChild : Base
{
}
public class GirlChild : Base
{
}
I would say that the standard approach here is to wrap the class you want to "inherit" as a protected instance variable and then emulate all the non-private members (method/properties/events/etc.) of the wrapped class in your container class. You can then mark this class and its appropiate members as virtual so that you can use standard polymorphism features with it.
Here's an example of what I mean. ClosedClass is the class contained in the assembly whose code to which you have no access.
public virtual class WrapperClass : IClosedClassInterface1, IClosedClassInterface2
{
protected ClosedClass object;
public ClosedClass()
{
object = new ClosedClass();
}
public void Method1()
{
object.Method1();
}
public void Method2()
{
object.Method2();
}
}
If whatever assembly you are referencing were designed well, then all the types/members that you might ever want to access would be marked appropiately (abstract, virtual, sealed), but indeed this is unfortunately not the case (sometimes you can even experienced this issue with the Base Class Library). In my opinion, the wrapper class is the way to go here. It does have its benefits (even when the class from which you want to derive is inheritable), namely removing/changing the modifier of methods you don't want the user of your class to have access to. The ReadOnlyCollection<T> in the BCL is a pretty good example of this.
Take a look at the Decorator pattern. Noldorin actually explained it without giving the name of the pattern.
Decorator is the way of extending behavior without inheriting. The only thing I would change in Noldorin's code is the fact that the constructor should receive an instance of the object you are decorating.
Extension methods provide an easy way to add additional method signatures to existing classes. This requires the 3.5 framework.
Create a static utility class and add something like this:
public static void DoSomething(this ClassA obj, int param1, string param2)
{
//do something
}
Add a reference to the utility class on the page, and this method will appear as a member of ClassA. You can overload existing methods or create new ones this way.

Categories

Resources