I want to inherit that a class has a property, but different implementations of this class will have different values for this property and the property should be available without instantiating an object.
Eg: every animal has a value numberOfLegs. For every cat it is 4 for every snake it is 0. Now I want to loop through some animal Types and print out how many legs that animal subclass has without creating an instance of that class.
You could give a chance to the following:
First declare your Animal abstract base class which will be responsible for storing types and numberoflegs
abstract class Animal
{
protected readonly static IDictionary<Type, int> _legsDictionary = new Dictionary<Type, int>();
}
And an Animal abstract class which has the static property NumberOfLegs:
abstract class Animal<T> :Animal where T : class
{
public static int NumberOfLegs
{
get => _legsDictionary.ContainsKey(typeof(T)) ? _legsDictionary[typeof(T)] : -1;
set
{
_legsDictionary[typeof(T)] = value;
}
}
}
And then just declare as many Animals as you want >>>
class Cat : Animal<Cat> { }
class Snake : Animal<Snake> { }
class Human : Animal<Human> { }
And testing:
static void Main(string[] args)
{
Cat.NumberOfLegs = 4;
Snake.NumberOfLegs = 0;
Human.NumberOfLegs = 2;
Console.WriteLine(Cat.NumberOfLegs);
Console.WriteLine(Snake.NumberOfLegs);
Console.WriteLine(Human.NumberOfLegs);
Console.ReadLine();
}
The thing you want to achieve isn't possible in the way you want it to be.
The static keyword stays persistent between every class.
What you can do is the following:
class Animal
{
public static int LegCount { get { return 0; } }
}
class Snake : Animal
{
public static new int LegCount { get { return 0; } }
}
class Human : Animal
{
public static new int LegCount { get { return 2; } }
}
class Cat : Animal
{
public static new int LegCount { get { return 4; } }
}
With the new keyword you can make each new type return a different value.
But note that a List<Animal> will always always return 0, since the new only hides within the type and is not the same as an override.
I guess you could also define your interface requirement (having a numberOfLegs property) by implementing an interface instead of inheriting from a base class. That way, you can place the static values at the levels of abstraction where they don't change across instances:
interface IAnimal
{
int numberOfLegs { get; }
}
class Snake : IAnimal
{
public static int numberOfLegs = 0;
int IAnimal.numberOfLegs
{
get { return numberOfLegs; }
}
}
class Cat: IAnimal
{
public static int numberOfLegs = 4;
int IAnimal.numberOfLegs
{
get { return numberOfLegs; }
}
}
Related
I want to output the numberOfLegs of my tiger1 instance. But the output is 0 instead of my expected 4. Where is my mistake? Please help the tiger to get his legs back.
using System;
namespace AbstractProperty
{
class MainClass
{
static void Main(string[] args)
{
Tiger tiger1 = new Tiger();
int result = tiger1.NumberOfLegs;
Console.WriteLine(result);
Console.Read();
}
public abstract class Animal
{
public abstract int NumberOfLegs { get; set; }
}
public class Tiger : Animal
{
private int numberOfLegs;
public override int NumberOfLegs
{
get
{
return numberOfLegs;
}
set
{
numberOfLegs = 4;
}
}
}
}
}
EDIT: I think it is not good to use numberOfLegs = 4 in a Setter
As I see, the set accessor for NumberOfLegs is never called, thus numberOfLegs has the default value 0.
You could write a constructor and assign some value to NumberOfLegs, which would be assigned 4 anyway as you have hard-coded 4 in the set accessor, i.e. if you write your constructor like this:
public Tiger() {
NumberOfLegs = 10;
}
The set accessor would be called and assign 4 (not 10) to numberOfLegs. Perhaps you have mixed up the concepts a bit here :)
EDIT 1: If you now understand that assigning a hard-coded value in the setter was not that great, and you don't want to do anything special in the setter, it would be better to use the traditional approach for properties:
private int numberOfLegs;
public override int NumberOfLegs
{
get
{
return numberOfLegs;
}
set
{
numberOfLegs = value;
}
}
Or simply
public override int NumberOfLegs { get; set; }
which does the same thing as above.
And assign value to NumberOfLegs in the constructor:
public Tiger()
{
NumberOfLegs = 4;
}
The NumberOfLegs property setter is not called as you're not changing the value anywhere in your code. The int value is zero by default. You can do one of the following:
Define the default value of numberOfLegs variable when declaring it:
private int numberOfLegs = 4;
Define the numberOfLegs value in constructor of Tiger class:
public class Tiger : Animal
{
private int numberOfLegs;
public Tiger() {
numberOfLegs = 4;
}
// ...
}
You are doing it all wrong...
Don't provide a setter for numberOfLegs. Just provide a getter. And then set the number of legs in the constructor, or just set the field directly, like so:
public abstract class Animal
{
public abstract int NumberOfLegs { get; }
}
public class Tiger : Animal
{
private int numberOfLegs = 4;
public override int NumberOfLegs
{
get
{
return numberOfLegs;
}
}
}
The reason your code wasn't working was because you weren't calling the setter for Tiger.NumberOfLegs, but of course if you did so you'd realise how wrong it was:
Tiger tiger1 = new Tiger();
tiger1.NumberOfLegs = 100;
int result = tiger1.NumberOfLegs; // Set to 100, but now it's 4! Urk.
Code to demonstrate the problem:
static void Main(string[] args)
{
var a = new A();
var b = new B();
Base<>[] all = new Base<>[] { a, b }; // doesn't work
}
class Base<T>
{
public string Caption { get { return typeof(T).ToString(); } }
}
class A : Base<A> { }
class B : Base<B> { }
Perhaps I went the wrong direction. Idea was to move Caption into base class (Base become generic). Non-generic version works without problems:
var all = new Base[] { a, b }; // no problems for as long as Base is not generic
There's no Type<?> in C# - you always have to specify a concrete generic type.
The only way around this is to make Base<T> inherit a non-generic base-class, or implement a non-generic interface. You could then use that as the type of the array.
EDIT:
In your case this is extremely simple, since the part of the interface you want doesn't include the generic type argument. So you can simply do either:
public abstract class Superbase
{
public abstract string Caption { get; }
}
public class Base<T>: Superbase
{
public override string Caption { get { return typeof(T).Name; } }
}
Or, using an interface:
public interface IBase
{
string Caption { get; }
}
public class Base<T>: IBase
{
public string Caption { get { return typeof(T).Name; } }
}
Your array would then be Superbase[] or IBase[], respectivelly. In both cases, you can see that I'm not actually providing an implementation - both the declarations are "abstract", in a sense.
In general, I'm trying to keep the non-generic stuff in a non-generic base class, rather than stuffing it in the derived generic classes. It just feels more clean :)
based on #Luaan ideea, here is an implementation:
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
var arr = new Base[] { a, b};
foreach (var obj in arr)
Console.WriteLine(obj.Caption);
Console.ReadKey();
}
}
public class Base<T> : Base
{
public override string Caption
{
get { return typeof (T).ToString(); }
}
}
public class A : Base<A> { }
public class B : Base<B> { }
public abstract class Base
{
public abstract string Caption { get; }
}
Instead of trying to use inheritance (which will lead to more problems down the line), use an extension method instead:
public interface IClassAORClassB {}
class A : IClassAORClassB { }
class B : IClassAORClassB { }
public static class Captions
{
public static string Caption<T>(this T obj) where T : IClassAORClassB
{
return obj.GetType().ToString();
}
}
static void Main(string[] args)
{
var a = new A();
var b = new B();
var all = new IClassAORClassB[] { a, b }; // works just fine
Console.WriteLine(all[0].Caption()); // prints A
Console.WriteLine(all[1].Caption()); // prints B
}
I have next code
class Base
{
public virtual int Prop { get; set; }
}
class Derived : Base
{
public override int Prop { get { return 1; } }
}
//...
Derived obj = new Derived();
int some = obj.Prop; //expected
obj.Prop = 10; //oops it works
The fact that the last line should complile seems not to be so obvious at first sight. In my program I have a situation when overriding some auto-implemented property in a such way would be a solution. I understand that it's not a good approach. What kind of refactoring can I do to avoid such inheritance and to clean my code? Thanks
A derived class has to implement the same interface as its base class - having a public setter be inaccessible from a derived class would break polymorphism.
If Prop needs to be inaccessible to clients, but you need to be able to set its value from within the class itself, you could declare it as:
public virtual int Prop { get; protected set; }
There probably isn't a single answer to this question, as it depends on the model for your specific application. If some derived classes need to allow writes to this property, but others don't, you could either throw an exception on an invalid write and handle it at run time, or perhaps implement the property using a protected backing field and only a getter, and then add a derived class that provides a SetProp() method for those classes that need it.
public class Base
{
protected int prop;
public virtual int Prop { get { return prop; } }
}
public class WriteableBase : Base
{
public virtual void SetProp(int prop) { this.prop = prop; }
}
class Base
{
public virtual int Prop { get; set; }
}
class Derived : Base
{
public new int Prop { get { return 1; } private set {} }
}
The problem is that if you cast your Derived to Base, you can set the property anyway. If the Property relay on a field, it will be overwriten.
Ex.:
class Base
{
protected int fProp;
public virtual int Prop { get { return fProp; } set { fProp = value; } }
}
class Derived : Base
{
public Derived()
{
fProp = 1;
}
public new int Prop { get { return fProp; } private set {} }
}
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//...
Derived obj = new Derived();
int some = obj.Prop; //expected
Base b = (Base)obj;
b.Prop = 10; //oops it works
Console.WriteLine(obj.Prop); =>it will show 10, not 1
Console.ReadKey();
}
}
}
A "better" approach to avoid this kind of problem is to avoid the use of a base class if you want to "change" something on a derived class. Or, put only the minimal content that must be implemente by ALL derived classes and let the derived classes implement any extra code that only they want.
Ex:
class Base
{
protected int fProp;
}
class Derived : Base
{
public Derived()
{
fProp = 1;
}
public int Prop { get { return fProp; } }
}
class Derived2 : Base
{
public int Prop { get { return fProp; } set { fProp = value; } }
}
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//...
Derived obj = new Derived();
int some = obj.Prop; //expected
Base b = (Base)obj;
//obj.Prop = 10; Compilation error
Console.WriteLine(obj.Prop);
Derived2 obj2 = new Derived2();
obj2.Prop = 10;
Console.WriteLine(obj2.Prop);
Console.ReadKey();
}
}
}
Also, you could "encapsulate" your base class:
class Derived
{
protected Base fBase;
public Derived()
{
fBase = new Base;
}
//implement enything that you need to access from Base class
public int Prop { get { return 1; } }
}
But I find this last one too "expensive"... :)
I think it´s not possible to get compiler-error in this case. Imagine further you´d declare obj not as Derived but as Base = new Derived(), how should compiler know which property to infer. So all you can do is to throw an exception during runtime within the derived setter telling that setting this property isn´t allowed fir this type.
class Base
{
public virtual int Prop { get; protected set; }
}
class Derived : Base
{
public override int Prop {
get { return 1; }
protected set {throw NotSupportedException();}
}
}
When compiling, C# transforms the getter and setter to individual methods (get_Prop and set_Prop).
Your code only implements the get in the Derived class, and the setremains that of the base class.
If this is your desired behavior, I don't find it to be wrong.
If you are trying to hide the setter in the Derived class, there is no elegant way to do it, so throwing an NotSupportedException is a solution.
class Base
{
public virtual int Prop { get; set; }
}
class Derived : Base
{
public override int Prop { get { return 1; } set { throw new NotSupportedException();}}
}
I've got a base class and three subtypes that derive from that class (see example below).
public abstract class Vehicle
{
string name;
string color;
}
public class Car : Vehicle
{
int nrofwheels;
}
public class Train : Vehicle
{
int nrofrailcars;
}
To make one of my method as generic as possible, I'd like to pass the base type as parameter and then detect hat subtype it is inside my method like this:
public static void main(string[] args)
{
public Car c = new Car();
public Train t = new Train();
public CheckType(Vehicle v)
{
if(v.GetType()==typeof(Car)) Console.Write(v.nrofwheels);
else Console.Write(v.nrofrailcars);
}
}
This doesn't seem to work, why and what else can I try?
[edit] I know that the class examples aren't complete, but I'd figured that its not necessary for this purpose.
You should refactor that class and move CheckType to Vehicle class and override it in descendant classes. And CheckType name is not the best one, it makes no sense since that method returns number of wheels / rails.
Something like this:
public abstract class Vehicle
{
string name;
string color;
public abstract int CheckType();
}
public class Car : Vehicle
{
int nrofwheels;
public override int CheckType()
{
return this.nrofwheels;
}
}
public class Train : Vehicle
{
int nrofrailcars;
public override int CheckType()
{
return this.nrofrailcars;
}
}
You can use as. You forgot to cast the object to make the properties accessible:
public CheckType(Vehicle v)
{
Train t = v as Train;
if (t != null)
Console.Write(t.nrofrailcars);
else
{
Car c = v as Car;
if (c != null)
Console.Write(c.nrofwheels);
}
}
Without any code in the subclasses, I'd like an abstract class to have a different copy of a static variable for each subclass. In C#
abstract class ClassA
{
static string theValue;
// just to demonstrate
public string GetValue()
{
return theValue;
}
...
}
class ClassB : ClassA { }
class ClassC : ClassA { }
and (for example):
(new ClassB()).GetValue(); // returns "Banana"
(new ClassC()).GetValue(); // returns "Coconut"
My current solution is this:
abstract class ClassA
{
static Dictionary<Type, string> theValue;
public string GetValue()
{
return theValue[this.GetType()];
}
...
}
While this works fine, I'm wondering if there's a more elegant or built-in way of doing this?
This is similar to Can I have different copies of a static variable for each different type of inheriting class, but I have no control over the subclasses
There is a more elegant way. You can exploit the fact that statics in a generic base class are different for each derived class of a different type
public abstract class BaseClass<T> where T : class
{
public static int x = 6;
public int MyProperty { get => x; set => x = value; }
}
For each child class, the static int x will be unique for each unique T
Lets derive two child classes, and we use the name of the child class as the generic T in the base class.
public class ChildA: BaseClass<ChildA>
{
}
public class ChildB : BaseClass<ChildB>
{
}
Now the static MyProperty is unique for both ChildA and ChildB
var TA = new ChildA();
TA.MyProperty = 8;
var TB = new ChildB();
TB.MyProperty = 4;
While this works fine, I'm wondering if there's a more elegant or built-in way of doing this?
There isn't really a built-in way of doing this, as you're kind of violating basic OO principles here. Your base class should have no knowledge of subclasses in traditional object oriented theory.
That being said, if you must do this, your implementation is probably about as good as you're going to get, unless you can add some other info to the subclasses directly. If you need to control this, and you can't change subclasses, this will probably be your best approach.
This is a little different than what you're asking for, but perhaps accomplishes the same thing.
class Program
{
static void Main(string[] args)
{
Console.WriteLine((new B()).theValue);
Console.WriteLine((new C()).theValue);
Console.ReadKey();
}
}
public abstract class A
{
public readonly string theValue;
protected A(string s)
{
theValue = s;
}
}
public class B : A
{
public B(): base("Banana")
{
}
}
public class C : A
{
public C(): base("Coconut")
{
}
}
There's an alternative solution which might or might not be better than yours, depending on the use case:
abstract class ClassA
{
private static class InternalClass<T> {
public static string Value;
}
public string GetValue()
{
return (string)typeof(InternalClass<>)
.MakeGenericType(GetType())
.GetField("Value", BindingFlags.Public | BindingFlags.Static)
.GetValue(null);
}
}
This approach is used in EqualityComparer<T>.Default. Of course, it's not used for this problem. You should really consider making GetValue abstract and override it in each derived class.
What about this?
class Base {
protected static SomeObjectType myVariable;
protected void doSomething()
{
Console.WriteLine( myVariable.SomeProperty );
}
}
class AAA : Base
{
static AAA()
{
myVariable = new SomeObjectType();
myVariable.SomeProperty = "A";
}
}
class BBB : Base
{
static BBB()
{
myVariable = new SomeObjectType();
myVariable.SomeProperty = "B";
}
}
It works for me.
Would be even nicer with Interface.
Simple solution: just use word "new".
public abstract class AbstractClass
{
public static int Variable;
}
public class RealizationA : AbstractClass
{
public new static int Variable;
}
public class RealizationB : AbstractClass
{
public new static int Variable;
}
And the result:
AbstractClass.Variable = 1;
RealizationA.Variable = 2;
RealizationB.Variable = 3;
Console.WriteLine(AbstractClass.Variable); //1
Console.WriteLine(RealizationA.Variable); //2
Console.WriteLine(RealizationB.Variable); //3
or you can use property:
//in abstract class
public static int Variable {get; set;}
//in child class
public static new int Variable {get; set;}
or function (but remember to add "new" to both variable and function):
//in abstract class
protected static int Variable;
public static int GetVariable() { return Variable; }
public static void SetVariable(int v) { Variable = v; }
//in child class
protected new static int Variable;
public static new int GetVariable() { return Variable; }
public static new void SetVariable(int v) { Variable = v; }
or you can use private variables (you don't need to use "new") with functions to get and set:
//in abstract class
private static int Variable;
//get and set methods
//in child class
private static int Variable;
//get and set methods