Changing the default value of an instance variable - c#

Suppose I have these codes (and the classes are in the same namespace):
class Animal
{
int numberOfLegs = 4; // initialized
public int returnNumberOfLegs()
{
return numberOfLegs;
}
}
class Snake
{
internal Animal myAnimalObject = new Animal();
myAnimalObject.numberOfLegs = 0; // why is this line not allowed?
}
class Program
{
public static void Main(string [] args)
{
Snake mySnakeObject = new Snake();
Console.WriteLine("Snake");
Console.WriteLine("Number of Legs: {0}", mySnakeObject.myAnimalObject.returnNumberOfLegs());
}
}
Observe the class Snake. When I place these 2 lines of code in Main(), it is possible/allowed and will work if I declare the variable numberOfLegs with the right access modifier. Why can't I do it in the class Snake itself? What should I do to allow it?
Note that the 2nd line of code from class Snake is invalid and these are the errors it produced:
1) Error 1 Invalid token '=' in class, struct, or interface member declaration
2) Error 2 'myNamespaceName.Snake.myAnimalObject' is a 'field' but is used like a 'type'
Thanks. I just want to learn about this.
Edit:
Okay, thanks guys. I know about constructors and inheritance, but somehow, I'm being forced to do it "the hard and not-so-smart" way, for learning purposes(?). And that I even had to set the default value to 4. Thank you for your replies. Plus, I just made up these classes.

Because executable code should be placed either in constructor or in some method/property.
You cannot place code just inside the class, put it in the constructor.
class Snake
{
internal Animal myAnimalObject = new Animal();
public Snake()
{
myAnimalObject.numberOfLegs = 0;
}
}
When you write
internal Animal myAnimalObject = new Animal();
in the class body, it's a kind of a syntax sugar; compiler will create constructor and put your code line inside it.
and it will look like
class Snake
{
internal Animal myAnimalObject;
public Snake()
{
myAnimalObject = new Animal();
myAnimalObject.numberOfLegs = 0;
}
}

First of all, you can't do this in the class initializer:
myAnimalObject.numberOfLegs = 0;
Since you're not setting a class member itself, but rather interacting with a class member, you'd have to do it in the constructor:
public Snake()
{
myAnimalObject.numberOfLegs = 0;
}
Also, in order to access numberOfLegs it would need to be internal or public:
internal int numberOfLegs = 4; // initialized
More to the point of the whole scenario however, this seems like a very odd abstraction. Though part of me applauds the use of composition instead of inheritance, this seems more like a case where inheritance is warranted. It seems that Animal really shouldn't be initializing any value for numberOfLegs by default. Indeed, Animal shouldn't even be a concrete object given the real-world concepts being modeled. Instead, I might try something like:
abstract class Animal
{
public abstract int NumberOfLegs { get; }
}
class Snake : Animal
{
public override int NumberOfLegs { get { return 0; } }
}
The idea being that a Snake is an Animal, that an Animal by itself can't exist unless it's a specific type of Animal, and that each individual type of Animal internally controls its own values and all the abstract Animal class does is define what those values need to be.

You should use inheritance instead. Make Animal an abstract class, base class for all animals. Composition (what you use now) does not make much sense in this case.
abstract class Animal
{
protected int numberOfLegs = 4; // default number of legs
public int NumberOfLegs { get { return numberOfLegs; } }
public Animal(int legs)
{
numberOfLegs = legs; // initialize number of legs
}
}
All concrete animals then derive from this class.
class Snake : Animal
{
public Snake() : base(0) // specify that number of legs is 0
{
}
}
The base(0) is a call to a base class constructor, so you are calling Animal(int legs) with an argument 0.

Do it like this:
abstract class Animal
{
private readonly int numberOfLegs;
protected Animal(int nrLegs = 4)
{
numberOfLegs = nrLegs;
}
public int returnNumberOfLegs()
{
return numberOfLegs;
}
}
class Snake : Animal
{
public Snake() : base(0)
{
}
}

Related

What is the logic behind casting classes in c#?

I am trying to understand the logic behind some C# casting conditions for classes, This is my testing code
File: example.cs
public class Animal { public string animal_name = "Animal"; }
public class Dog : Animal { public string dog_name = "Dog"; }
public class Class1
{
public void createObjects()
{
var animal1 = new Animal();
printAnimalName(animal1);
}
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.dog_name);
}
}
In my Main function, I call the call createObjects function as follows:
static void Main(string[] args)
{
Class1 c1 = new Class1();
c1.createObjects();
Console.ReadLine();
}
Running the code above gives an error
System.NullReferenceException:'Object reference not set to an instance of an object'
I understand that this is the way it should be, due to the casting in:
var dog1 = my_animal as Dog;
But what is the logic behind it? Why can't we call the function printAnimalName by passing an Animal object for it? This should be possible as per my understanding, because the function expects an Animal object.
After that var dog1 = my_animal as Dog; // dog1 is of type Dog you need to add only null check:
if(dog1 != null)
{
Console.WriteLine(dog1.dog_name);
}
I think you need to learn about polymorphism, abscract classes and interfaces.
public abstract class FourLeggedAnimal
{
public int GetLegCount()
{
return 4;
}
}
public class Dog : FourLeggedAnimal
{
public string GetScientificName()
{
return "doggus scientificus";
}
}
public class Cat : FourLeggedAnimal
{
public string GetServant()
{
return "human";
}
}
public class AnimalInformer
{
public void DisplayInformation(FourLeggedAnimal animal)
{
Console.WriteLine("It has {0} legs", animal.GetLegCount());
if (animal is Dog)
Console.WriteLine("Its scientific name is {0}", ((Dog)animal).GetScientificName());
if (animal is Cat)
Console.WriteLine("Its servant is {0}", ((Cat)animal).GetServant());
}
}
Here you use the absract class to provide base functionality to all other classes derived from it. All classes derived from FourLeggedAnimal have a method GetLegCount() that returns the number of legs.
But a cat has a servant a dog doesnt have, it just has a friend(both humans, but different relations). So the dog needs no method "GetServant" but the cat does. -> Differenct implementations in 2 seperate classes
Another example with interfaces is that each derived class needs to provide that functionality.
public interface IMovableObject
{
int GetMaxSpeed();
}
public class Car : IMovableObject
{
public int GetMaxSpeed()
{
return 100;
}
}
public class Human : IMovableObject
{
public int GetMaxSpeed()
{
return 20;
}
}
public static class SpeedChecker
{
public static void CheckSpeed(IMovableObject speedster)
{
Console.WriteLine("Checking Speed..");
int speed = speedster.GetMaxSpeed();
if (speed > 50)
Console.WriteLine("It's really fast!");
else
Console.WriteLine("Just a turtle or something similar...");
}
}
Now, if you have a Method getting a IMovableObject that is actually a car, you call the implementation of Car:
Car c = new Car();
Human h = new Human();
Console.WriteLine("Checking Car..");
SpeedChecker.CheckSpeed(c);
Console.WriteLine("Checking Human..");
SpeedChecker.CheckSpeed(h);
-> returns:
Checking Car...
Checking Speed...
It's really fast!
Checking Human...
Checking Speed...
Just a turtle or something similar...
These are 2 uses where you derive classes and use castings to get certain functionality or use the basetype without casting but still getting different functionality
Your problem is here:
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.dog_name); //Animal does not have this property!
}
Casting does not invoke a constructor. This means that dog_name is null, as my_animal does not have a dog_name property. I think you missed something on inheritance here.
This is actually an example that happens in more complex form in the real world; Given class A, B inherits from A. Both have the same properties because of inheritance. Then someone makes a different property with a similar, but not congruous property name and uses it for the same function in the child object. Welcome to code smell city.
To fix your function so it comes across as a dog, you'd do two things:
public class Animal { public string animal_name = "Animal"; }
//since we want a different default, we can
//can make the change in the constructor
public class Dog : Animal
{
Dog(){ this.animal_name = "Dog"; }
//if you really, really want a second name string, you can do this:
public string Dog_Name
{
get { return this.animal_name; }
set { this.animal_name = value; }
}
}
Then, you need to make your method call the appropriate property.
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.animal_name);
}
I also recommend changing your public fields to properties and possibly override ToString() when all you want to do with an object is return a string representing it.

Why can't I access methods specific to my child class?

In C#, I have a parent class with a public member. I want to derive the parent class, then derive the class of the public member, so as to create and access new methods, as follows...
public class Animal { }
public class Sheep : Animal {
public void makeALamb() { }
}
public class Farm
{
public Animal myAnimal;
}
public class SheepFarm : Farm {
public void SheepFarm() {
this.myAnimal = new Sheep();
this.myAnimal.makeALamb();
}
}
This code doesn't compile. "Animal does not contain a definition for makeALamb()". But what I want to do is the essence of polymorphism, no? What am I missing? I'm greatly looking forward to finding out.
Thanks in advance!
Because myAnimal is of type Animal. As such, it can only access members of Animal... and Animal doesn't have a method makeALamb.
The right hand side of the assignment here:
this.myAnimal = new Sheep();
..says what it is. The left hand side says what your code sees it as. The left hand side in your assignment is:
public Animal myAnimal;
// ^^^^^^
Now.. pretend that what you've tried is possible.. consider this:
this.myAnimal = new Snake();
this.myAnimal.makeALamb(); // what does it call here?
this.myAnimal = new Giraffe();
this.myAnimal.makeALamb(); // what here?
..what should happen when you call makeALamb on a Snake instance? ...
If I'm guessing correctly what you're intending to do, consider using generics:
public class Farm<TAnimal> where TAnimal : Animal
{
public TAnimal myAnimal;
}
public class SheepFarm : Farm<Sheep>
{
public void SheepFarm()
{
this.myAnimal = new Sheep();
this.myAnimal.makeALamb();
}
}
makeALamb() is a method of Sheep, not Animal. Sheep derives from Animal, not the other way around.
this.myAnimal is defined as an Animal. Animal does not have a makeALamb method. Since you put a Sheep in this.myAnimal, you could cast it:
((Sheep)this.myAnimal).makeALamb();
This effectively says: "Take this.myAnimal, treat is as a Sheep and call makeALamb() on it". If this.myAnimal is not really a Sheep at run-time, you'll get an exception.
The idea is that your Animal can be instantiated as Sheep, but it will handle only the members defined on Animal. It is as simple as: Sheep is an Animal, but Animal is not a Sheep, so the Animal can not makeALamb() :)
You have to cast your Animal instance to Sheep if you want to access makeALamb method.
public void SheepFarm()
{
this.myAnimal = new Sheep();
((Sheep)this.myAnimal).makeALamb();
}
Without a cast myAnimal is considered as type of Animal and therefore you can only access the members of Animal and the members of base class(es) of Animal (which there is no base class olf Animal in this case).
On the other hand, ofcourse this is not an elegant and secure way to access a class member.If you want to access some common members via a base class instance, then you should declare that members in your base class (maybe as abstract or virtual), and then implement (or override) them in derived classes.
you have not defined the Farm class well. Here is example:
public class Animal { }
public class Sheep : Animal {
public void makeALamb() { }
}
public class Goat: Animal {
public void makeAGoat() { }
}
public class Farm
{
public Goat myGoat;
public Sheep mySheep;
}
public class MyFarm : Farm {
public void MyFarm() {
this.mySheep= new Animal();
this.mySheep.makeALamb();
}
}
Every animal is not goat but every goat is an animal.
Since, you want to use polymorphism, change your code to:
public abstract class Animal
{
public abstract void makeChild();
}
public class Sheep : Animal
{
public override void makeChild()
{
Console.WriteLine("A lamb is born.");
}
}
public class Cow : Animal
{
public override void makeChild()
{
Console.WriteLine("A calf is born.");
}
}
public class Farm
{
public Animal myAnimal;
}
public class SheepFarm : Farm
{
public SheepFarm()
{
this.myAnimal = new Sheep();
this.myAnimal.makeChild();
}
}
public class CowFarm : Farm
{
public CowFarm()
{
this.myAnimal = new Cow();
this.myAnimal.makeChild();
}
}
and, use the following "Main()" method:
class Program
{
static void Main(string[] args)
{
Farm sf = new SheepFarm();
Farm cf = new CowFarm();
}
}
However, I should point to you that this is not a good use case scenario. A better and simpler use case of polymorphism would be to get rid of the Farm classes and use the following "Main()" method instead of the previous one:
class Program
{
static void Main(string[] args)
{
Animal[] animals = {
new Sheep(),
new Cow(),
new Sheep(),
new Cow(),
new Cow()
};
foreach (Animal animal in animals)
{
animal.makeChild();
}
}
}

c# polymorphism derive class to other derive class

I have a class for example Tile, with derive classes TileA, TileB... TileF.
Now I want always that class TileF changes with a call into TileE.
And also TileE to TileD, and you can see the patern.
Can I specify it directly in TileF where it changes into.
I'm looking at Activator.CreateInstance(), but this gives me a object class, and not the wanted derive class.
How can I solve this?
I do this in my Main loop, where I specified that Tile tile = TileF;
then i want to do something like: tile.change() and that it changes in a new TileE
Some kind of code:
Class Tile{
public abstract int Number{ get; }
}
Class TileF : Tile{
public override int Number
{
get
{
return 1;
}
}
}
Class TileE : Tile{
public override int Number
{
get
{
return 2;
}
}
}
Class Main{
Tile tile = new TileF;
//change tile to TileE
tile = tile.ToNextTileType();
}
When TileE and TileF are siblings, ie when they derive from a common baseclass, you cannot convert them directly.
There are several possible solutions but you don't provide much detail.
I think that maybe you should not use inheritance. Could a simple enum TileType solve your problem(s)?
You might want to look at interfaces. Interface lets unrelated objects be treated as the same thing when you reference a type of the Interface type e.g.
class ClassOne : ICommon;
class ClassTwo : ICommon;
class ClassThree : ICommon;
ClassOne x = new ClassOne();
ClassTwo y = new ClassTwo();
ClassThree z = new ClassThree();
List<ICommon> data = new List<ICommon>();
data.Add(x);
data.Add(y);
data.Add(z);
foreach(ICommon item in data)
{
item.InterfaceMethodOne();
}
This might not be what you want but it is worth looking into.
James :-)
There is a difference between the static and the dynamic type of an object. The static type of an object can be changed, that is you may write BaseType base = (BaseType)new DerivedType();. Changing the static type of an instance is called casting.
The compiler will restrict the call to methods, fields and properties present in the BaseType and all of its base types. The dynamic type of an object however may never change and in this case base still has the dynamic type DerivedType. The condition if (base is DerivedType) will return true in this case. You can only "change" the dynamic type by instantiating a new object of the target type and copy the desired values to the new instance. This process is called mapping.
Btw, Activator.CreateInstance will only give you an instance of the static type object, but likely with a different dynamic type. You can change the static type by casting it to a type that you know the object should have: (DerivedType)Activator.CreateInstance(typeof(DerivedType)). You can also use the generic variant, then this cast is done within the method: Activator.CreateInstance<DerivedType>(). Semantically there is no difference, except that the generic variant is easier to read.
EDIT:
Does this solve your problem?
public abstract class Tile {
public abstract int Number { get; }
public abstract Tile Advance();
}
public class TileA : Tile {
public override int Number { get { return 1; } }
public override Tile Advance() { return new TileB(); }
}
public class TileB : Tile {
public override int Number { get { return 2; } }
public override Tile Advance() { return new TileC(); }
}
public class TileC : Tile { ... }
You can also define the "state machine" in the abstract class like so:
public abstract class Tile {
public abstract int Number { get; }
public sealed Tile Advance() {
if (this is TileA) {
return new TileB();
else if (this is TileB) {
return new TileC();
}
}
}
Another alternative is of course to model the state machine entirely in one object:
public enum TileState { TileA, TileB, TileC };
public class Tile {
private TileState state = TileState.TileA; // initial state
public int Number {
get {
switch (state) {
case TileState.TileA: return 1;
case TileState.TileB: return 2;
...
default: return -1; // or throw exception
}
}
}
public void Advance() {
switch (state) {
case TileState.TileA: state = TileState.TileB; break;
case TileState.TileB: state = TileState.TileC; break;
...
default: // exception ?
}
}
}
In the last example, the behavior of your object changes depending on the state variable. It's not a new instance, but it can do something completely different. I hope something of this could help.
I made an error in designing TileF/TileE etc. It was good enough to make a TileN, with a property that is replacing the inner working of a tile. This way I don't have to substitute a class, and thus avoiding this problem.

c# abstract classes

i have to create a fake DMV program that calculates annual fees, for commercial and private vehicles. Those two classes will be abstract and they will polymophism from a class named all vehicles.
My instructor wants only one object created the entire program(in main) but since my top 3 tier classes are abstract. I can't create an object with them i.e. vehicles = new vehicles();
so my question is how do i create only one object since they are abstract? If you have any questions feel free to ask, I might have not explained this well...
Your class structure will look something like:
abstract class Vehicle
{
protected abstract int BaseFee { get; }
protected abstract int ExtraFee { get; }
public int CalculateFee()
{
return BaseFee + ExtraFee;
}
}
abstract class CommercialVehicle : Vehicle
{
protected override int BaseFee
{
return 100;
}
}
class LightDutyTruck : CommercialVehicle
{
protected override int ExtraFee
{
return 50;
}
}
class Semi : CommercialVehicle
{
protected override int ExtraFee
{
return 150;
}
}
[etc...]
abstract class PrivateVehicle : Vehicle
{
protected override int BaseFee
{
return 25;
}
}
class Sedan : PrivateVehicle
{
protected override int ExtraFee
{
return 15;
}
}
and so on, for each class. In your Main method, you would create the instance based on input, but your actual variable would be declared as type Vehicle. The actual calculation will take effect based on the instance that you create:
Vehicle v;
switch(input)
{
case "semi":
v = new Semi();
break;
case "truck":
v = new LightDutyTruck();
break;
...
}
int fee = v.CalculateFee();
You seem to be a bit confused. "All Vehicles" should be abstract. "Commercial Vehicle" and "Private Vehicle" should not be abstract, unless there are concrete subclasses of those two.
You may also not be understanding what your instructor means by "only one object", since that doesn't make sense.
Maybe you are to make one object which represents the DMV, but the definition of that object includes instances of other objects.
class DMV {
private List<Vehicle> vehicles = new List<Vehicle>();
...
}
Your instructor may want you to instantiate multiple objects through a reference to the abstract base class:
Vehicle conveyance;
conveyance = new PrivateVehcicle();
conveyance.Drive();
conveyance.Stop();
// or whatever ...
conveyance = new CommercialVehcicle();
conveyance.Drive();
conveyance.Stop();
i.e. you have a single object reference (conveyance) that behaves polymorphically depending on the concrete type you've instantiated.

How to make an Abstract Base class IComparable that doesn't compare two separate inherited classes?

(C#, VS2008) In a program I'm working on, I've got lots of objects that all have an ID and implement IComparable so that List<>-s of the various objects are easily searchable by ID. Since I hate copy/pasting code, I thought I'd abstract that bit of functionality down to a base class, like so:
using System;
namespace MyProg.Logic
{
abstract class IDObject : IComparable<IDObject>
{
private int miID;
public int ID
{
get { return miID; }
set { miID = value; }
}
public IDObject(int ID)
{
miID = ID;
}
#region IComparable<IDObject> Members
int IComparable<IDObject>.CompareTo(IDObject other)
{
return miID.CompareTo(other.miID);
}
#endregion
}
}
The drawback I see to that is that two separate classes that each inherit it would be directly comparable using .CompareTo() and I was hoping to enforce that each class that inherits from IDObject is only Comparable to others of the exact same class. So I was hoping to figure out how to do that and came up with this
using System;
namespace MyProg.Logic
{
abstract class IDObject : IComparable<T> where T : IDObject
{
private int miID;
public int ID
{
get { return miID; }
set { miID = value; }
}
public IDObject(int ID)
{
miID = ID;
}
#region IComparable<T> Members
int IComparable<T>.CompareTo(T other)
{
return miID.CompareTo(other.miID);
}
#endregion
}
}
But that gives a compile error of "Constraints are not allowed on non-generic declarations"
Looking at it, I'm sure there's a way to do something like that so that each class is only comparable to other instances of that same class, but I can't tease out the syntax.
You can use the Curiously Recurring Template Pattern to solve this problem.
abstract class Base<T> : IComparable<T> where T : Base<T> {
public int Rank { get; set; } // Order instances of derived type T by Rank
public int CompareTo(T other) { return Rank.CompareTo(other.Rank); }
}
class Foo : Base<Foo> {}
class Bar : Base<Bar> {}
static class Program {
static void Main() {
var foo1 = new Foo { Rank = 1 };
var foo2 = new Foo { Rank = 2 };
var bar1 = new Bar { Rank = 1 };
var bar2 = new Bar { Rank = 2 };
Console.WriteLine(foo1.CompareTo(foo2));
Console.WriteLine(bar2.CompareTo(bar1));
//error CS1503: Argument '1': cannot convert from 'Bar' to 'Foo'
//Console.WriteLine(foo1.CompareTo(bar1));
}
}
I think you've got bigger problems than just making sure that the derived class types are the same. You are also saddling the derived class with the responsibility to generate a unique ID. That requires the derived class to be aware what other IDs were assigned previously. Realistically, that requires a class factory. You'll need to enforce that by making the constructor of your abstract class protected.
Not very practical. If the ID is just an opaque number that establishes object identity then consider assigning the ID yourself. Use a static member to keep track of the last assigned one. Now it becomes simple, and you don't have to worry about derived class types anymore.

Categories