I know that syntactically and conceptually the concepts of "virtual" and "static" members are diametrically opposed, but I'm trying to push the envelope a bit and see if there's a way to achieve the following:
Let's say I have an abstract class Animal, which has a property NumberOfLegs. My Cat class should have NumberOfLegs defined as 4, while Spider should have 8 legs. I would want to have code like this (obviously the code below will not compile):
public abstract class Animal {
public static abstract int NumberOfLegs { get; }
public void Walk() {
// do something based on NumberOfLegs
}
}
public class Cat : Animal {
public static override int NumberOfLegs { get { return 4; } }
}
public class Spider : Animal {
public static override int NumberOfLegs { get { return 8; } }
}
I want it to be static, because it's not dependent on instance; it's dependent only on the subclass type.
How would you do this?
I think the best compromise for you is to create a constant in each class for the number of legs. A constant is basically a static member which is readonly, which for this example makes sense, otherwise make it static.
Next, I would define an abstract Property for the Animal class and override it each subclass. This would allow inheritance and polymorphism to work, but each instance of the class would still reference the same value.
public abstract class Animal
{
public abstract int NumberOfLegs { get; }
public void Walk()
{
// do something based on NumberOfLegs
}
}
public class Cat : Animal
{
private const int NumLegs = 4;
public override int NumberOfLegs { get { return NumLegs; } }
}
public class Spider : Animal
{
private const int NumLegs = 8;
public override int NumberOfLegs { get { return NumLegs; } }
}
As far as not being to override static methods, I know it isn't what you want to hear but that's not possible. First of all, you use static members like Animal.Legs or Cat.Legs by specifying the class and not from an instance of the object. Therefore, if you define it as static, you won't even have access on it from an instance of the class, and there is no idea of polymorphism either (i.e. a function accepting a generic "Animal" cannot get how many legs it has and have it call the correct Property). If you are interested in how this works I suggest you read about Virtual Tables
Related
Can i constrain the type that is passed to my method in a way that catches this type of error when compiling instead of running?
My current code looks like this:
void Main()
{
var dog = new Dog();
SaveAnimal(dog);
}
void SaveAnimal(Animal animal) {
var isAnimal = animal.GetType().UnderlyingSystemType == typeof(Animal);
Debug.Assert(isAnimal, "You can not save dogs!");
}
class Animal {
public int Legs { get; set; }
}
class Dog : Animal {
public int TailLength { get; set; }
}
No, there is no way in the language to statically catch this as a usage error.
You can assert this at runtime as you are doing it already. It's against the spirit of inheritance, though, because a fundamental assumption is that derived types must substitute for the base type (the Liskov substitution principle).
Maybe you can make the animal save itself by giving Animal a new method abstract void Save(). Then, each animal decides what to do. Dog can then throw a NotSupportedException.
Yes, but only with a workaround using generics and interfaces.
What you would need to do is to declare 3 interfaces
public interface ISaveAbleBase { }
public interface ISaveAble : ISaveAbleBase{ }
public interface INotSaveAble : ISaveAbleBase { }
Now you need to give your Animal class a generic parameter and constraint it to be of type ISaveAbleBase.
class Animal<T> where T: ISaveAbleBase
{
public int Legs { get; set; }
}
This way you can now specify in the derived classes wether they can or cannot be saved:
class Dog : Animal<INotSaveAble>
{
public int TailLength { get; set; }
}
Then you could make your method generic and constrain the type only to aminals that can be saved
void SaveAnimal<T>(T animal) where T: Animal<ISaveAble>
Now the result looks the following way:
void Main()
{
var dog = new Dog();
SaveAnimal(dog); // does not compile
Animal<ISaveAble> generalAnimal = new Animal<ISaveAble>();
SaveAnimal(generalAnimal); // compiles
}
Disclaimer: this construct would also allow you to have a general Animal that cannot be saved:
Animal<INotSaveAble> generalAnimalNotSave = new Animal<INotSaveAble>();
SaveAnimal(generalAnimalNotSave); // does not compile
PS. This answer is inspired by this post
There is no standard way how to do this, but there is a simple (and stupid) workaround.
using System.Diagnostics;
namespace Test
{
internal static class Program
{
private static void Main()
{
var dog = new Dog();
SaveAnimal(dog);
}
private static void SaveAnimal(Animal animal)
{
var isAnimal = animal.GetType().UnderlyingSystemType == typeof(Animal);
Debug.Assert(isAnimal, "You can not save dogs!");
}
private static void SaveAnimal(ICanNotSave animal)
{
Debug.Fail("Can not save");
}
}
internal class Animal
{
public int Legs
{
get; set;
}
}
internal interface ICanNotSave
{
}
internal sealed class Dog : Animal, ICanNotSave
{
public int TailLength
{
get; set;
}
}
}
When you have two SaveAnimal method, where one of for Animal and other is for a interface, that is implemented on all descendants that can not be saved, the compiler report a CS0121 error.
The call is ambiguous between the following methods or properties: 'Program.SaveAnimal(Animal)' and 'Program.SaveAnimal(ICanNotSave)'
Remember it is still possible to use the SaveAnimal method when you use it like this: SaveAnimal((Animal)dog)
I was recently coming up with some rather funky singleton work and discovered that I can access a protected static member from any unique inherited type using the same base of inheritance where generics are used. An example of what I'm talking about is as follows:
public abstract class Class<T>
{
protected static int number = 5;
public void Print()
{
Console.WriteLine(number);
}
}
public class ClassA : Class<ClassA>
{
}
public class ClassB : Class<ClassB>
{
public ClassB()
{
number = 1;
}
}
public class ClassC : Class<ClassC>
{
public ClassC()
{
number = ClassA.number;//I don't want to be able to see "number"
}
}
Since generics are in use here, each unique inheriting type gets its own "number" (which is what I want). But I don't like that I can access "number" from other types inheriting the same base type when generics are used. Is there a way to fix this? And also why does this happen (I understand why it happens with inheritance without generics, but it doesn't seem right that it happens with generics)?
I don't like that I can access "number" from other classes inheriting the same base class when generics are used. Is there a way to fix this?
The only true fix is to declare separate private static variables for each class. This will keep you from being able see the number variable in one class type from any other class type.
public abstract class Class<T>
{
private static int number = 5;
public void Print()
{
Console.WriteLine(number);
}
}
public class ClassA : Class<ClassA>
{
}
public class ClassB : Class<ClassB>
{
private static int number;
public ClassB()
{
number = 1;
}
}
public class ClassC : Class<ClassC>
{
private static int number;
public ClassC()
{
number = 123; // Cannot see ClassA.number because it is private to `Class<T>`
}
}
The side effect is being caused by declaring the variable protected static and using it with inheritance. It is unclear why you would attempt to do that when the behavior you are after is that of a private static field.
You can use the private modifier to make the static member invisible to descendents. Use protected only if you want the descendants to be able to access it. It makes no difference generic vs. non.
public abstract class Class<T>
{
private static int number = 5; //Private now
public void Print()
{
Console.WriteLine(number); //Works
}
}
public class ClassA : Class<ClassA>
{
//No number
}
public class ClassB : Class<ClassB>
{
public ClassB()
{
number = 1; //Will not compile
}
}
public class ClassC : Class<ClassC>
{
public ClassC()
{
number = ClassA.number;//Will not compile
}
}
If you want the static variable to be accessible only to some descendants and not others, define the variable in the first class in the inheritance chain that needs access:
public abstract class Class<T>
{
}
public class ClassA : Class<ClassA>
{
static private int number = 7;
}
public class ClassB : Class<ClassB>
{
static private int number = 7;
public ClassB()
{
ClassA.number = 5; //Does not compile
ClassB.number = 6;
}
}
public class ClassC : Class<ClassC>
{
static private int number = 7;
public ClassC()
{
Console.WriteLine(ClassA.number); //Does not compile
Console.WriteLine(ClassB.number); //Does not compile
Console.WriteLine(ClassC.number); //Compiles
}
}
You cannot define something in an ancestor class and remove it from a descendant.
I have a class Foo, which is a base class for a lot other classes such as Bar and Baz, and I want to do some calculation within Foo using the static members in Bar and Baz, as shown below:
public class Foo{
public result1 {
get{
return field1;
}
}
}
public class Bar : Foo{
public const int field1 = 5;
}
public class Baz : Foo{
public const int field1 = 10;
}
The only solution I can think of is wrap all the fields in a container, add an extra identifier for each object, and use a function to return the fields, like so
Bar : Foo{
public readonly int id = 0;
public static Wrapper wrapper;
}
public Wrapper GetWrapper(int id){
switch(id){
case 0:
return Bar.wrapper;
}
}
However, as you can see, I need to maintain one additional class and function, and I'd rather not to fragment my code. Is there any alternative?
Edit
What you are asking for, i.e. accessing a static or const value in a subclass from a base class is technically possible, but doing so will violate the principals of good SOLID OO design. Also, since you will need an instance of a specific subclass in order to be able to 'reason over' the type of the subclass in order to obtain the appropriate field1, there's little point approaching this problem statically.
Instead, the common, cleaner, approach here is to use subtype polymorphicism which will allow a calling method in the base class, or a method in an external class altogether, to access the appropriate value for 'field1' based on the subclass. This allows control over the value returned to remain inside the appropriate subclasses (i.e. as per your words, the code won't become "fragmented").
Alternative solution using subclass polymorphicism (recommended)
A subclass polymorphic approach (i.e. with the virtual/abstract and override keywords) will allow you to encapsulate the retrieval of a value (or object) which is customizable for each subclass. Here, the abstraction remains conceptually at "give me an integer value", and then the sub-class-specific implementations of 'how' to return the value can be abstracted (hidden) from the caller. Also, by marking the base property as abstract, you will force all subclasses to implement the property, so that the requirement to provide a value isn't forgotten about.
i.e. I would recommend a polymorphic approach like this:
public abstract class Foo
{
public abstract int Result { get; }
}
public class Bar : Foo
{
// This is implementation specific. Hide it.
private const int field1 = 5;
public override int Result
{
get { return field1; }
}
}
public class Baz : Foo
{
public override int Result
{
// No need for this implementation to be a constant ...
get { return TheResultOfAReallyComplexCalculationHere(); }
}
}
If there are no other reusable concrete methods on the base class Foo, then you could also model the abstraction as an interface, with the same effect:
public interface IFoo
{
int Result { get; }
}
Approaching this problem without polymorphicism (Not recommended)
Any compile-time attempt to access static fields on subclasses will typically require code somewhere to switch (or map) on the actually type of the subclass instance, e.g.:
public class Foo
{
public int result1
{
get
{
switch(this.GetType().Name)
{
case "Bar":
return Bar.field1;
case "Baz":
return Baz.field1;
default:
return 0;
}
}
}
public void MethodRequiringValueFromSubclass()
{
Console.WriteLine(result1);
}
}
public class Bar : Foo
{
public const int field1 = 5;
}
public class Baz : Foo
{
public const int field1 = 10;
}
The problem here is that the Open and Closed principal is violated, as each time a new sub class is added, the result1 method would need to be changed to accomodate the new class.
I'd suggest to use abstract function rather that using static member.
public abstract class Foo{
public result1 {
get{
return get_field1();
}
}
protected abstract int get_field1();
}
public class Bar : Foo{
public const int field1 = 5;
protected override int get_field1() { return field1;}
}
public class Baz : Foo{
public const int field1 = 10;
protected override int get_field1() { return field1;}
}
You either add constructor parameter to your Foo class which can be passed from inheritors, thus you don't need extra classes also you'll have less coupling
public class Foo
{
private readonly int _field1;
public Foo(int field1)
{
_field1 = field1;
}
}
or you can use it exactly from inheritors type as static/const members are members of class type
public class Foo
{
public result1
{
get
{
return Bar.field1;
}
}
}
but this gives your code less flexibility and more coupling.
Also you have an option by using virtual properties which you can implement in derrived classes and use in base:
public class Foo
{
public virtual int Field { get { return 0; } }
}
Instead of making Foo abstract as other answers suggested you can use virtual and override result1 in each child class
public class Foo
{
public virtual int result1 { get; }
}
public class Bar : Foo
{
public const int field1 = 5;
public override int result1
{
get { return field1; }
}
}
public class Baz : Foo
{
public const int field1 = 10;
public override int result1
{
get { return field1; }
}
}
If you want default result1 to return something else than 0 you can give it another value
public class Foo
{
public virtual int result1 { get; } = -1;
}
I always feel like a jerk when I answer my own question... Yet didn't see what I was expecting so I might as well just share what I've got after a night of mind boggling.
The reason I don't want to make the calculation abstract/virtual is because there are many subclasses and the formula is the same for all of them. I just refuse to type the same code 10-20 times repeatedly.
Couldn't make the static fields non static either, as they should be accessible at a class level plus they can get big, and they are the same for all instances.
The only solution I can come up that minimizes code fragment is something like this
public class Foo {
public class Wrapper {
Fields...
}
public Wrapper wrapper; // reference
public int result1 { get; }
}
public class Bar : Foo {
public static Wrapper subclassWrapper; // put in the implementation
public Bar() : base(){
wrapper = subclassWrapper;
}
}
So each instance now needs to hold an extra reference, however I don't need to keep a function. The wrapper is kept within the base class so it is less fragmented.
Let there be class NaturalFood and two classes inherit from this class; class Fruits and class Vegetables
abstract class NaturalFood
{
enum AllList
{
//empty list as a placeholder
}
protected string Name;
}
class Fruits : NaturalFood
{
enum AllList
{
Apple = 1,
Banana = 2
}
}
class Vegetables : NaturalFood
{
enum AllList
{
Carrot = 1,
Potatoes = 2
}
}
I want to enforce that any class derived from class NaturalFood must declare and/or override the AllList enumeration. Effectively the enumeration will contain list specific to the derived class. How do I do this ?
Edit: My basic requirement is that each class deriving from a base class must have its own list of "something" that is specific to it. Enumeration is just a way of creating a list. I hope you get the gist from my example. I want to take advantage of what Enumeration offers viz. intellisense, toString() etc.
Edit2: Isn't my example very practical enough ? If I put the entire enumeration in the base class (NaturalFood), how do I know which of the enumerated values are specific to which derived class ? Let us say each derived class is "publishing something" it has to offer in form of enumerated constants and I want to enforce this constraint on every derived class. So in other words, my question is how to enforce a constraint on derived class like in scenario described here ?
Actually, there's no sense to override these values. Actually, the advantages of override is that you can call a method of a derived class without knowing the derived class itself.
For example :
static void Main()
{
NaturalFood food = GetSomeFood(); // At this point, we don't know the actual type
food.SomeMethodInBaseClass(); // ok
}
static NaturalFood GetSomeFood()
{
if(somecondition) {
return new Fruits();
}
else{
return new Vegetables();
}
}
public abstract class NaturalFood
{
public abstract void SomeMethodInBaseClass();
}
public class Fruits : NaturalFood
{
public override void SomeMethodInBaseClass(){
Console.WriteLine("I'm a fruit");
}
}
public class Vegetables : NaturalFood
{
public override void SomeMethodInBaseClass(){
Console.WriteLine("I'm a vegetable");
}
}
No imagine what you wanted to do. In the main method, try to call the AllList :
static void Main()
{
NaturalFood food = GetSomeFood(); // At this point, we don't know the actual type
food.SomeMethodInBaseClass(); // ok
food.AllList.XXXX; // What? it won't compile
}
This won't compile. The compiler has no way to know the actual derived class to infer the available enumeration values.
However, if you remove the enumeration from the base type, this will works :
static void Main()
{
NaturalFood food = GetSomeFood(); // At this point, we don't know the actual type
food.SomeMethodInBaseClass(); // ok
Fruits f = new Fruits();
Console.WriteLine( f.AllList.Apple); // Ok
Vegetable v = new Vegetable ();
Console.WriteLine( v.AllList.Potatoe); // Ok
}
But as you can see, you have to know explicitly the actual type, and thus, make the polymorphic useless.
[Edit] It's hard to answer to your second edit. Actually there are many many ways to validate such constraint. Without more context it may be difficult to answer. The most simple way I think, is to add to each derived class a overriden property that describe what kind of enumeration is accepted.
public enum NaturalFoodType {
Unknown = 0,
Apple= 1,
Banana = 2,
Potatoe = 3,
Cucumber = 4
}
public abstract class NaturalFood
{
public abstract void SomeMethodInBaseClass();
public abstract IEnumerable<NaturalFoodType> AcceptedFoodType { get; }
public bool IsValid(NaturalFoodType type){
return AcceptedFootType.Contains(type);
}
}
public class Fruits : NaturalFood
{
public override void SomeMethodInBaseClass(){
Console.WriteLine("I'm a fruit");
}
public override NaturalFoodType {
get {
yield return NaturalFoodType.Apple;
yield return NaturalFoodType.Banana;
}
}
}
public class Vegetables : NaturalFood
{
public override void SomeMethodInBaseClass(){
Console.WriteLine("I'm a vegetable");
}
public override NaturalFoodType {
get {
yield return NaturalFoodType.Potatoe;
yield return NaturalFoodType.Cucumber;
}
}
}
But honestly, it start to add a lot of plumbing code, that become quite unreadable. You should consider the problem at a higher scope to find an acceptable solution.
This is not possible because enums are types, not class members... and the fact they are declared inside a class doesn't make them members of that class, they are just nested. Every class can and has to define it's own private enum AllList type... so your actual code is the only possible way to go.
If you want to obtain something like this and you have only few values to deal with, stick with properties overrides:
class A
{
public virtual String Value
{
get
{
return "A";
}
}
}
class B : A
{
public override String Value
{
get
{
return "B";
}
}
}
I'm trying to set up an inheritance hierarchy similar to the following:
abstract class Vehicle
{
public string Name;
public List<Axle> Axles;
}
class Motorcycle : Vehicle
{
}
class Car : Vehicle
{
}
abstract class Axle
{
public int Length;
public void Turn(int numTurns) { ... }
}
class MotorcycleAxle : Axle
{
public bool WheelAttached;
}
class CarAxle : Axle
{
public bool LeftWheelAttached;
public bool RightWheelAttached;
}
I would like to only store MotorcycleAxle objects in a Motorcycle object's Axles array, and CarAxle objects in a Car object's Axles array. The problem is there is no way to override the array in the subclass to force one or the other. Ideally something like the following would be valid for the Motorcycle class:
class Motorcycle : Vehicle
{
public override List<MotorcycleAxle> Axles;
}
but the types have to match when overriding. How can I support this architecture? Will I just have to do a lot of run-time type checking and casting wherever the Axles member is accessed? I don't like adding run-time type checks because you start to lose the benefits of strong typing and polymorphism. There have to be at least some run-time checks in this scenario since the WheelAttached and Left/RightWheelAttached properties depend on the type, but I would like to minimize them.
Use more generics
abstract class Vehicle<T> where T : Axle
{
public string Name;
public List<T> Axles;
}
class Motorcycle : Vehicle<MotorcycleAxle>
{
}
class Car : Vehicle<CarAxle>
{
}
abstract class Axle
{
public int Length;
public void Turn(int numTurns) { ... }
}
class MotorcycleAxle : Axle
{
public bool WheelAttached;
}
class CarAxle : Axle
{
public bool LeftWheelAttached;
public bool RightWheelAttached;
}
2 options spring to mind. 1 is using generics:
abstract class Vehicle<TAxle> where TAxle : Axle {
public List<TAxle> Axles;
}
The second uses shadowing - and this assumes you have properties:
abstract class Vehicle {
public IList<Axle> Axles { get; set; }
}
class Motorcyle : Vehicle {
public new IList<MotorcycleAxle> Axles { get; set; }
}
class Car : Vehicle {
public new IList<CarAxle> Axles { get; set; }
}
void Main() {
Vehicle v = new Car();
// v.Axles is IList<Axle>
Car c = (Car) v;
// c.Axles is IList<CarAxle>
// ((Vehicle)c).Axles is IList<Axle>
The problem with shadowing is that you have a generic List. Unfortunately, you can't constrain the list to only contain CarAxle. Also, you can't cast a List<Axle> into List<CarAxle> - even though there's an inheritance chain there. You have to cast each object into a new List (though that becomes much easier with LINQ).
I'd go for generics myself.
I asked a similar question and got a better answer, the problem is related to C#'s support for covariance and contravariance. See that discussion for a little more information.