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.
Related
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; }
}
}
public class Gameplay {
public static int count = 0;
AClass aClass = new AClass(ref count);
}
public class AClass {
public int count { get; set; }
public AClass(ref int c) {
this.count = c;
}
public void printCount() {
Console.WriteLine(this.count.ToString());
}
}
I have two classes like the ones above. Suppose the count variable of Gameplay increases in another class that does Gameplay.count++. I want AClass.count to always be equal to Gameplay.count.
Now, surely I could just use Gameplay.count inside AClass but if I have different counts to pass in different instances of AClass it's better to have the reference to the count you want to access. The above example always writes 0 even if Gameplay count has increased.
What would you expect this code to do?
int c = 0;
int count = c;
c++;
c and count are both references, yet mutating c somehow does not change the value of count.
It's exactly the same situation in your code.
In your code, this line:
this.count = c;
does not copy the reference to c. It copies the value at the time of the assignment to the value-type backing field for count.
You can pass a lambda expression to the constructor if you need AClass to be able to access the value of some arbitrary integer.
public class Gameplay {
public static int count = 0;
AClass aClass = new AClass( () => count );
}
public class AClass {
public int count { get { return this.getCount(); } }
private readonly Func<int> getCount;
public AClass(Func<int> getCount) {
this.getCount = getCount;
}
public void printCount() {
Console.WriteLine(this.count.ToString());
}
}
In your constructor:
public AClass(ref int c) {
this.count = c;
}
... even though the parameter c is passed by reference, as soon as you assign it to this.count, the value gets copied. So any changes to c or Gameplay.count will not be reflected in this.count.
That's going to be challenging, because integers are value types.
You might try using a class that has a Count property, and pass that in instead. If you have multiple objects with Count properties, you could declare an interface with a property of Count (let's call it IHasCount) and have AClass take an instance of IHasCount as its parameter.
Your design begins to sound like it uses the Singleton pattern, which is discouraged nowadays. You might want to read up on that.
Wrap the count into another class
public class CounterHolder
{
public int count = 0;
}
public class Gameplay
{
public static CounterHolder counterHolder = new CounterHolder();
AClass aClass = new AClass(counterHolder);
public void DoSomething()
{
// Something
counterHolder.count++;
aClass.printCount();
}
}
public class AClass
{
private CounterHolder _counterHolder;
public AClass(CounterHolder counterHolder)
{
_counterHolder = counterHolder;
}
public void printCount()
{
Console.WriteLine(_counterHolder.count.ToString());
}
}
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'm trying to create a class which takes value a as a parameters in it's constructor.
It has a private member variable which stores this value. The value should not be changed afterwards.
Here's what I have, it works but I don't think it's the best solution out there:
internal class Foo
{
private int a;
public int A
{
get
{
return this.a;
}
}
public Foo(int a)
{
this.a = a;
}
}
So this way you can not access a from outside of the class, and A-property only has a get method. However, you can still change a from inside the class, and using a property which only returns one variable and nothing else feels stupid.
Am I doing this right, or is there a way to improve my code/more proper way to do this?
Additionally declare your private field readonly and you're there!
public class Foo
{
public Foo(int bar)
{
this.bar = bar;
}
public int Bar
{
get
{
return bar;
}
}
private readonly int bar;
}
“In C# 6 and later, you can initialize auto-implemented properties similarly to fields”. Just like you can initialize a readonly field in a constructor, you can initialize a get-only auto-implemented property in a constructor. Thus, the following now compiles:
public class Class1
{
public int A { get; }
public Class1(int a)
{
A = a;
}
}
…and the following yields an error:
public class Class1
{
public int A { get; }
public Class1(int a)
{
A = a;
}
public void Mutate()
{
// Class1.cs(11,9,11,10): error CS0200: Property or indexer 'Class1.A' cannot be assigned to -- it is read only
A++;
}
}
I like it—you get the terseness of field initialization with the interface/OOP-friendliness of properties.
internal class Foo
{
private readonly int _a;
public int A
{
get
{
return _a;
}
}
public Foo(int a)
{
_a = a;
}
}
This should do it.
I'm trying to override a property in my program.
Here is basically what I'm trying to do :
class A { public int test = 7; }
class B : A { public int test = 8; }
class Program
{
static void Main(string[] args)
{
A test1 = new A();
A test2 = new B();
Console.WriteLine(test1.test);
Console.WriteLine(test2.test);
}
}
This displays 7 in both case when I'd like it to display 8 in the 2nd case....
I've tried virtual and override as well as new (public new int test = 8;)
But it doesn't seem to work
And yes I know I should use private and getters. I just want to know if it's possible ?
Edit : I'm not a native C# programmer so forgive me if i mix the terms (such as field and propertys)!
I'm trying to override a property in my program.
class A { public int test = 7; }
The problem is that int test is not a property, it is a public field. Fields cannot be overriden.
Here is an example of overriding a property:
class A {
public virtual int test {
get {return 7;}
}
}
class B : A {
public override int test {
get {return 8;}
}
}
Here is a demo of this code on ideone.
test is a field, not a property. You must change it to a property and add the virtual modifier to allow it to be overriden in a subclass. You must then use the override keyword to override the value returned in class B:
class A
{
public virtual int test
{
get { return 7; }
}
}
class B : A
{
public override int test
{
get { return 8; }
}
}
Change this
A test2 = new B();
with this
B test2 = new B();
If you create test2 as A you call A methods