I want to instantiate new object of type Dog. Dog class implements interface IAnimal. Animal can make baby animal and that baby animal can grow to be big animal of type dog.
public interface IAnimal
{
BabyAnimal baby();
int NumberOfLegs { get; set; }
}
public class Dog:IAnimal
{
public Dog()
{
}
public int NumberOfLegs { get; set; }
public BabyAnimal baby()
{
}
}
public class BabyAnimal
{
public IAnimal WillGrowToBe(BabyAnimal baby)
{
//here I want to instantiate new Dog object
}
}
You can model this more strongly, if you introduce the concept of baby and grown animals, in a generic fashion:
public interface IAnimal
{
int NumberOfLegs { get;}
}
public interface IBabyAnimal<TGrownAnimal>
: IAnimal
where TGrownAnimal : IGrownAnimal
{
TGrownAnimal WillGrowToBe();
}
public interface IGrownAnimal : IAnimal
{
}
public class Catepillar : IBabyAnimal<Butterfly>
{
public int NumberOfLegs { get;} = 100;
public Butterfly WillGrowToBe() => new Butterfly();
}
public class Butterfly : IGrownAnimal
{
public int NumberOfLegs { get; } = 0;
}
You can interact with every one of the animals as a simple IAnimal for things like leg count, and nicely, you can write something like this:
public static class Extensions
{
public static TGrown GrowUp<TGrown>(this IBabyAnimal<TGrown> baby)
where TGrown : IGrownAnimal
=> baby.WillGrowToBe();
}
Which you can then use against any baby animal to get the grown form.
If you want to distinguish baby animal (e.g. Pup) and adult one (Dog) you can implement 3 interfaces:
// Animal in the most general: all we can do is to count its legs
public interface IAnimal {
// get: I doubt if we should maim animals; let number of legs be immutable
int NumberOfLegs { get; }
}
// Baby animal is animal and it can grow into adult one
public interface IBabyAnimal : IAnimal {
IAdultAnimal WillGrowToBe()
}
// Adult animal can give birth baby animal
public interface IAdultAnimal : IAnimal {
IBabyAnimal Baby();
}
// Dog is adult animal, it can birth pups
public class Dog : IAdultAnimal {
public Dog()
public int NumberOfLegs { get; } => 4;
public Baby() => new Pup();
}
// Pup is baby animal which will be dog when grow up
public class Pup : IBabyAnimal {
public Pup()
public int NumberOfLegs { get; } => 4;
public WillGrowToBe() => new Dog();
}
Related
I have a class structure like this:
BaseAnimal.cs:
public abstract class BaseAnimal
{
public string? Species { get; set; }
public double Price { get; set; }
}
Then I have this two classes:
public abstract class Carnivore : BaseAnimal
{
public double MeatFood { get; set; }
}
public abstract class Herbivore : BaseAnimal
{
public double GreenFood { get; set; }
}
And then I have the sub classes:
public class Ape : Herbivore
{
public Ape()
{
Species = "Ape";
GreenFood = 10.0;
Price = 10000.0;
}
}
Then I have a facotry which is already working with this line to get all the attributes from an animal:
public BaseAnimal[] Animals = prototypes.Values.ToArray();
And in my Main class I would like to read the properties of the Animals:
private void cboAnimals_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine(animalFactory.Animals[0].);
}
The problem with this code is, that I cannot access the properties specified in the Herbivore.cs and Carnivore.cs
What you should do is use Composition.
public interface IFood {
public double Food { get; set; }
}
public class Herbivore {
public double Food { get; set; }
}
public class Carnivore {
public double Food { get; set; }
}
public interface IAnimal {
string? Species { get; set; }
double Price { get; set; }
}
public class Animal {
string? Species { get; set; }
double Price { get; set; }
}
public class Ape {
private IAnimal _animal;
private IFood _food;
public Ape(IAnimal animal, IFood food) {
_animal = animal;
_food = food;
}
}
public void main(string[] args) {
IFood herbivore = new Herbivore(){Food = 10};
IAnimal ape = new Animal(){
Price = 1000;
Species = "Ape";
};
Ape ape = new Ape(ape, herbivore);
}
Now you can compose any class of type animal you want, you can reuse the implementation of IAnimal and IFood on other types, make new ones? Like Omnivore?
you can implement different species, and or "price" and load it into any new class like "dog" or "cat" you want, and compose that object with your Interfaces. Thus not needing to rewrite your tests, you don't need to have multiple implementations of say ... "Speak" on dogs that all do a "bark" you can have one class that does "bark" and then compose it into all dog like animals.
Just consider how easy it is now to implement a behaviour like "consume" that will work across all herbivores, omnivores or carnivores?
You only have to write 3 unit tests, one for each, not one for each animal type you eventually create, because they exist with dependency separation.
And Consume would work on any parameter of type food, so you don't even have to care if you find new ways of defining food, like a rock-eater or something :)
or if you had to descript plants, as something that "consumes" and you needed sunlight as a food source? Super simple to do, You wouldn't need to write x-amount of plant type unit tests for that either.
Composition over inheritance is by far the better choice to implement code in OOP.
Simplest is probably to check the type:
var foodAmount = animalFactory.Animals[0] switch {
Carnivore c => c.MeatFood ,
Herbivore h => h.GreenFood ,
_ => throw new InvalidOperationException()
};
But this is a typical example of inheritance taught in introductory programming. As a general rule, if you need to check the type, you might not have thought thru your type system well enough. The idea with inheritance is that everything implementation specific should be delegated to the implementation, so the user of the object do not need to know the concrete type.
I have some difficulty providing concrete recommendations since the example is so artificial, But I would recommend reading Eric Lippert series on Wizards and Warriors for a nice introduction to inheritance, and how people often do it wrong.
The problem is that animals array is of type BaseAnimal. You'll need to unbox it (ie cast it to it's subtype), you'll need some logic to check the type also, so something like
if (obj is Herbivore)
{
var herb = (Herbivore)obj;
herb.Greenfood= 123m;
}
It seems messy but at some point you need to get the concrete type.
Animals is an array of BaseAnimal. This class doesn't have a MeatFood or a GreenFood property. That's why you can't access these properties. If you could access them, this code would be possible:
BaseAnimal animal = new Ape();
Console.WriteLine(animal.MeatFood);
But Ape has no MeatFood property. If you want to access these properties, you have know whether your Animals[0] is a Carnivore or a Herbivore:
private void cboAnimals_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(animalFactory.Animals[0] is Carnivore carnivore)
{
Debug.WriteLine(carnivore.MeatFood);
}
else if (animalFactory.Animals[0] is Herbivore herbivore)
{
Debug.WriteLine(herbivore.GreenFood);
}
}
But maybe you realize at this point that you won't get good code by this. This is a sign that your class structure is not the best. In fact, why do you have two properties MeatFood and GreenFood? What is the difference between them? Both are of a double type. Hence maybe you should have a Food property in your BaseAnimal class and distinguish the type of food by an enum:
public enum FoodType
{
Meat,
Green
}
public abstract class BaseAnimal
{
public string? Species { get; set; }
public double Price { get; set; }
public double Food { get; set;}
public abstract FoodType FoodType {get;}
}
public abstract class Carnivore : BaseAnimal
{
public override FoodType FoodType{ get { return FoodType.Meat; } }
}
public abstract class Herbivore : BaseAnimal
{
public override FoodType FoodType{ get { return FoodType.Green; } }
}
I have written a Collection like this:
class AnimalCollection<TValue> where TValue : Animal, new()
{
void Add(TValue value){};
void AddNew()
{
Add(new TValue());
}
}
I have some Classes which are derived from Animal:
class Animal
{
string Name;
}
class Fish : Animal
{
Fish(){};
}
class Mammal : Animal
{
Mammal(){};
}
As next i want to treat all collections the same way.
static void Main(string[] args)
{
var FishAquarium = new AnimalCollection<Fish>();
var MammalEnclosure = new AnimalCollection<Mammal>();
foo(FishAquarium);
foo(MammalEnclosure);
}
Question 1: I want to pass every AnimalCollection, which type need 'zoo'?
static void foo(AnimalCollection<Animal> zoo)
{
foreach(var animal in Zoo)
Console.WriteLine(animal.Name);
zoo.AddNew();
}
Question 2: What is the best practice to generalize a generic class?
Update:
More specific, i have a class which get any AnimalCollection.
class ZooController
{
public AnimalCollection<Animal> Animals{get; set;}
}
Generics would work:
static void foo<T>(AnimalCollection<T> zoo) where T : Animal, new()
{...}
However, it is usually not a good idea to roll your own collection types - it tends to create more confusion than it helps. You may want to consider justList<T>, or IList<T> at a push.
You say you don't want to use generics; that is IMO a silly decision since they solve exactly this problem, but you can also use covariance; if you have:
interface IAnimalCollection<out TValue> : IEnumerable<TValue>
{
void AddNew();
}
and:
class AnimalCollection<TValue> : IAnimalCollection<TValue>
where TValue : Animal, new()
{...}
then you can use:
static void foo(IAnimalCollection<Animal> zoo)
{
foreach (var animal in zoo)
Console.WriteLine(animal.Name);
zoo.AddNew();
}
and your code:
var FishAquarium = new AnimalCollection<Fish>();
var MammalEnclosure = new AnimalCollection<Mammal>();
foo(FishAquarium);
foo(MammalEnclosure);
will work fine; but - this is making work for no reason - simple generics via the foo<T> method shown above is simpler and more direct.
Try this approach:
class Program
{
static void Main(string[] args)
{
List<IAnimal> animals = new List<IAnimal>() { new Animal("Fuffy"), new Fish("Fishy"), new Mammal("Mommy") };
OutputAnimalsNames(animals);
}
private static void OutputAnimalsNames(List<IAnimal> animals)
{
foreach (IAnimal animal in animals)
{
Console.WriteLine(animal.Name);
}
}
}
public interface IAnimal
{
Guid Guid { get; }
string Name { get; }
}
public class Animal : IAnimal
{
public Guid Guid { get; private set; }
public string Name { get; set; }
public Animal(string name)
{
this.Name = name;
this.Guid = Guid.NewGuid();
}
}
public class Fish : Animal
{
public Fish(string name) : base(name)
{
}
}
public class Mammal : Animal
{
public Mammal(string name) : base(name)
{
}
}
Let's say I have following code:
public abstract class Vehicle
{
public Transmission MyTransmission;
public int NumberOfWheels;
public int NumberOfSeats;
public int Weight;
public int TopSpeed; //etc.
}
public class Car : Vehicle
{
public int SteeringWheelSize = 10;
}
public class Truck : Vehicle
{
public int SteeringWheelSize = 20;
}
public class Bike : Vehicle
{
}
public class FourWheelTransmission
{
public Vehicle ParentVehicle;
public Transmission(Vehicle vehicle)
{
ParentVehicle = vehicle;
//here, I want to access the SteeringWheelSize from its ParentVehicle object.
}
}
To accomplish the goal in the last comment, what should be the best method? Of course, one way would be making two abstract classes: "public abstract class TwoWheelVehicle" and "public abstract class FourWheelVehicle", but what if we don't want to repeat all the similar properties common in both FourwheelVehicle and TwoWheelVehicle, is there any other way to allow FourWheelTransmission class to access its vehicle's SteeringWheelSize?
How about that:
public abstract class Vehicle
{
public Transmission MyTransmission;
public int NumberOfWheels;
public int NumberOfSeats;
public int Weight;
public int TopSpeed; //etc.
}
public abstract class FourWheelVehicle : Vehicle
{
public int SteeringWheelSize;
}
public class Car : FourWheelVehicle
{
public Car()
{
SteeringWheelSize = 10;
}
}
public class Truck : FourWheelVehicle
{
public Truck()
{
SteeringWheelSize = 20;
}
}
public class FourWheelTransmission
{
public FourWheelVehicle ParentVehicle;
public Transmission(FourWheelVehicle vehicle)
{
ParentVehicle = vehicle;
//here, I want to access the SteeringWheelSize from its ParentVehicle object.
}
}
Without Bike in the picture, it would sound to me like Vehicle should have a SteeringWheelSize which is assigned a value in the constructor, called by the subclass.
public abstract class Vehicle
{
public int SteeringWheelSize { get; private set; }
...
protected Vehicle(int steeringWheelSize)
{
SteeringWheelSize = steeringWheelSize;
}
}
public class Car : Vehicle
{
public Car() : base(20)
{
}
}
...
However, you now have a problem: Bike doesn't have a steering wheel, so your model no longer fits. If you want to be able to model both a Bike and a Car, you perhaps need another class between Vehicle and Car, and put the SteeringWheelSize member there instead - then FourWheelTransmission would be passed that instead. (This is effectively MarcinJuraszek's answer, although I would give the new intermediate class a constructor accepting the steering wheel size as above.)
That's then slightly awkward in terms of using up the one shot of inheritance - you're effectively deciding that "whether or not it has a steering wheel" is the one important distinction; you can't make a different distinction elsewhere in the same way, due to the lack of multiple inheritance of implementation in C#.
Alternatively, both Car and Truck could implement an interface saying that they've got a steering wheel, and FourWheelTransmission could use that instead. At that point you could still use an intermediate abstract class, but you wouldn't have to:
public interface ISteerable
{
int SteeringWheelSize { get; }
}
public abstract class Vehicle
{
// Properties here
}
public class Car : Vehicle, ISteerable
{
public SteeringWheelSize { get { return 20; } }
}
...
public class FourWheelTransmission
{
// We know we can safely cast this to ISteerable
private Vehicle vehicle;
private FourWheelTransmission(Vehicle vehicle)
{
this.vehicle = vehicle;
}
public static FourWheelTransmission<T> FromSteerableVehicle(T vehicle)
where T : Vehicle, ISteerable
{
}
}
Note the slight awkwardness here - we can't express to the compiler that FourWheelTransmission will have a single variable which is both a subclass of Vehicle and an implementation of ISteerable, unless we make FourWheelTransmission itself generic and use constraints. I've got a workaround above, where you can only construct an instance of FourWheelTransmission based on such a type, but without FourWheelTransmission being generic. If Vehicle were an interface instead, then ISteerable could extend IVehicle.
Also please note that this requires you to use properties rather than public fields - interfaces can't specify fields. I think this is a good thing anyway - I dislike public fields intensely, as they're exposing an implementation detail through the public API.
One simple solution is:
You can give a default value to two wheeler steering size also (say -1) and use if conditions in the logic wherever steering size is used.
I would create an interface.
public abstract class Vehicle {
public Transmission MyTransmission { get; set; }
public int NumberOfWheels { get; set; }
public int NumberOfSeats { get; set; }
public int Weight { get; set; }
public int TopSpeed { get; set; } //etc.
}
public interface ISteeringWheelVehicle {
int SteeringWheelSize { get; set; }
}
public class Car : Vehicle, ISteeringWheelVehicle {
public Car() {
SteeringWheelSize = 10;
}
public int SteeringWheelSize { get; set; }
}
public class Truck : Vehicle, ISteeringWheelVehicle {
public Truck() {
SteeringWheelSize = 20;
}
public int SteeringWheelSize { get; set; }
}
public class Bike : Vehicle {
}
public class FourWheelTransmission {
public Vehicle ParentVehicle;
public Transmission(Vehicle vehicle) {
ParentVehicle = vehicle;
if (ParentVehicle is ISteeringWheelVehicle) {
var steeringWheelSize = ((ISteeringWheelVehicle)ParentVehicle).SteeringWheelSize;
}
}
}
I want to be a little be more descriptive in my class names. I have three identical classes that look like this:
public class Dog
{
public string name;
public int id;
public Dog(){}
public Dog(DataRow dr)
{
name = dr["Name"];
id = dr["Id"];
}
}
public class Cat
{
public string name;
public int id;
public Cat(){}
public Cat(DataRow dr)
{
name = dr["Name"];
id = dr["Id"];
}
}
public class Horse
{
public string name;
public int horseId;
public Horse(){}
public Horse(DataRow dr)
{
name = dr["Name"];
horseId= dr["horseId"];
}
}
How do I avoid code duplication by using a base class? What are the best practicies? pplease note that horse has a property called HorseId instead of Id. Thanks.
Use inheritance.
public class Animal
{
public string name;
public int id;
public Animal() {}
public Animal(DataRow dr)
{
name = (string)dr["Name"];
id = (int)dr["Id"];
}
}
// unfortunately, constructors aren't inherited automatically in C#.
public class Cat : Animal
{
public Cat() : base() {}
public Cat(DataRow dr) : base(dr) {}
}
public class Dog : Animal
{
public Dog() : base() {}
public Dog(DataRow dr) : base(dr) {}
}
public class Horse: Animal
{
public int horseId { get { return id; } set { id = value; } }
public Horse() : base() {}
public Horse(DataRow dr) : base(dr) {}
}
EDIT: as Blorgbeard says, you can make Animal an abstract class if you want - that will prevent instantiation (new Animal() will be illegal; client code will have to pick a specific subclass).
I would make an interface called IAnimal that has properties name and id and have all 3 classes above implement this interface. Note is is slightly different than what you have here, as what you have here shows public variables, not public properties. If you want to maintain variables, then I would use a base class Animal with public variables name and id and convert horseId to a property that, interally, gets and sets the base id property like this public int horseId { get { return base.id; } set { base.id = value; } }
I'd do something like this - an abstract base class.
public abstract class Animal {
public string name;
public int id;
protected Animal() {}
protected Animal(DataRow dr) {
name = (string)dr["Name"];
id = (int)dr["Id"];
}
}
public class Cat : Animal {
public Cat() : base() {}
public Cat(DataRow dr) : base(dr) {}
}
Then just add a property to Horse (still leaving id as well)
public class Horse : Animal {
public int horseid { get { return id; } set { id = value; } }
public Horse() : base() {}
public Horse(DataRow dr) : base(dr) {}
}
This method doesn't allow you remove/hide id in the Horse class, so you will have both id and horseid, but they will use the same variable underneath.
As far as some good examples on object oriented design, I'd recommend two books.
The Object Oriented Thought Process
Agile Principles, Patterns and Practices in C# by Robert C. Martin. This book is just awesome at explaining great principles of OOP.
I have something similar to the following, but I cannot provide House or Farm objects to the PrintShelterAddress method:
public interface IAnimal { };
public interface IDomesticAnimal : IAnimal { };
public interface IHouseAnimal : IDomesticAnimal { };
public interface IFarmAnimal : IDomesticAnimal { };
public class Animal : IAnimal { }
public class DomesticAnimal : Animal, IDomesticAnimal { }
public class Lion : Animal { }
public class Cat : DomesticAnimal, IHouseAnimal { }
public class Horse : DomesticAnimal, IFarmAnimal { }
public interface IAnimalShelter<T> where T : IDomesticAnimal { String Address { get; set; } };
public interface IHouse : IAnimalShelter<IHouseAnimal> { };
public interface IFarm : IAnimalShelter<IFarmAnimal> { };
public class AnimalShelter<T> : IAnimalShelter<T> where T : IDomesticAnimal { public String Address { get; set; } }
public class House : AnimalShelter<IHouseAnimal>, IHouse { }
public class Farm : AnimalShelter<IFarmAnimal>, IFarm { }
class Program
{
static void Main(string[] args)
{
PrintShelterAddress(new House() { Address = "MyHouse" }); // Error: argument type 'House' is not assignable to parameter type 'IAnimalShelter<IDomesticAnimal>'
// This makes sense as House is a IAnimalShelter<IHouseAnimal>
// and IHouseAnimal cannot be cast to its parent IDomesticAnimal
IAnimalShelter<IDomesticAnimal> nonDescriptShelter = new House(); // InvalidCastException: Unable to cast object of type 'House' to type 'IAnimalShelter`1[IDomesticAnimal]'.
}
static void PrintShelterAddress(IAnimalShelter<IDomesticAnimal> nonDescriptShelter)
{
Console.WriteLine(nonDescriptShelter.Address as string);
}
}
What I tried:
Manual cast:
PrintShelterAddress((IAnimalShelter<IDomesticAnimal>)new House() { Address = "MyHouse" });
Compiles but as expected, throws a run-time exception: Unable to cast object of type 'House' to type 'IAnimalShelter`1[IDomesticAnimal]'.
What else I tried:
static void PrintShelterAddress(dynamic nonDescriptShelter)
{
Console.WriteLine(nonDescriptShelter.Address);
}
This works but I am not keen on using dynamic.
My best solution:
Adding an non generic base interface to IAnimalShelter<T> and using that:
public interface IAnimalShelter { String Address { get; set; } };
public interface IAnimalShelter<T> : IAnimalShelter where T : IDomesticAnimal { };
static void PrintShelterAddress(IAnimalShelter nonDescriptShelter) { ... }
So...
Is there a better solution than using dynamic or adding a base interface to IAnimalShelter<T>?
Hmm.. Try to make your interfaces covariant:
public interface IAnimalShelter<out T> : .....