Consider the following classes:
abstract class Cog {}
class BigCog: Cog {}
class SmallCog: Cog {}
abstract class Machine {}
class BigMachine: Machine {}
class SmallMachine: Machine {}
Now all the machines work with cogs, but BigMachine
only works with BigCog
and SmallMachine
only works with SmallCog
. I'd like to make this nicely typed, so that I could to this:
Machine machine;
BigMachine bigMachine;
SmallMachine smallMachine;
Cog cog;
BigCog bigCog;
SmallCog smallCog;
bigMachine.cog = bigCog; // OK
smallMachine.cog = smallCog; // OK
bigMachine.cog = smallCog; // Compiler error, type mismatch
smallMachine.cog = bigCog; // Compiler error, type mismatch
machine.cog = cog; // Runtime error if type mismatch
machine.cog = bigCog; // Runtime error if type mismatch
machine.cog = smallCog; // Runtime error if type mismatch
bigMachine.cog.BigCogMethod(); // OK, BigMachine.cog is of type BigCog
smallMachine.cog.SmallCogMethod(); // OK, SmallMachine.cog is of type SmallCog
The only way I can think of achieving this is if I can BOTH override AND shadow the cog
property:
abstract class Machine
{
public virtual Cog cog { get; set; }
}
class BigMachine
{
public override Cog cog
{
get
{
return base.cog;
}
set
{
if ( value != null && !(value is BigCog) )
throw new ArgumentException();
base.cog = value;
}
}
new public BigCog cog // Compiler error, member "cog" already declared
{
get { return (BigCog)base.cog; }
set { base.cog = value; }
}
}
Unfortunately the compiler complains that there already is a class member named cog
, so I cannot both override it and shadow at the same time. Is there some other elegant pattern that can solve this dilemma? Note that I do need to act on abstract Machine
type variables and do the machine.cog = cog;
thing, so making a generic class like class BigMachine: Machine<BigCog>
doesn't work.