Using base classes to add objects to a collection - c#

I have two custom objects, lets say Cat and Dog. I want to create an observable collection that can hold either of these objects, as they are very similar. Can I use base classes to do this?
If so, would you mind providing a quick example.
And if I do use a base class, does that mean if I want to use common fields, I should put those into the base class?
EDIT: I'm hoping to then bind a WPF datagrid to the properties of these objects. I don't know if it's possible to bind a datagrid in WPF to two different kind of objects...

Yes, in that case you can use a base class:
public class Pet
{
public int Id { get; set; }
public string Name { get; set; }
public void Run() { }
}
public class Cat: Pet
{
public string Meow()
{
return "Meow";
}
}
public class Dog :Pet
{
public string Bark()
{
return "Whow";
}
}
Notice however, that when you place instances of both classes in one collection you can access only members of the base class.
So this code is valid:
var collection = new ObservableCollection<Pet> {new Cat(), new Dog()};
foreach (var pet in collection)
{
pet.Run();
}
but you cannot use methods Meow() and Bark() unless you use explicit casting.
Be careful with moving too many members to the base class - in the example above Meow() doesn't make sense for the Dog and Bark() for the Cat. If you need to use some method specific to the derived class you could check the type with:
pet.GetType()
and then cast object to the derived type:
var cat = (Cat)pet;
cat.Meow();

Yes. You can use a base class say animal. And yes if they have common fields such as name, type, etc.. they can go in there.
class Animal {
public String name;
}
Then just extend that. But you can also extend the functionality.
class Dog extends Animal {
public void bark();
}
Now anything that asks for something of type Animal can receive Dog.
public void addToCollection(Animal animal)
addToCollection(new Dog());
This is actually the backbone for Java's Object.

Yes to the properties, that's sort of the point of base classes. You express the commonality in the base and the specificity in the derived classes. As for whether the base class is the best place for an observable collection, well, it depends. You need to give some more insight into the need and the expected usage. It's doable though.
Check out ObservableCollection<T> also.

Related

Using abstract class as parameter in base class constructor to have more specific types in derived classes

Coming from data science I'm trying to learn oop for software development using c#.
I am trying to set up a base class (e.g. Aliments) from which a few other even more specific custom lists classes are going to derive (e.g. Fruits and Vegs). On the side I have individual Fruit and and Veg classes that derive from Aliment. In the end I want instances of Fruits/Vegs to have a List of Veg/Fruit propriety (along with a few proprieties and methods specific to the Fruits and Vegs classes). But I want this list propriety to be implemented in the Aliments base class along with a few methods to manage it (for instance RemoveRipe(), SortBySize()...)
I tried to put a List propriety in the Aliments class and then make the derived classes (Fuits/Vegs) call the base constructor with a List<Fruit> or List<Veg>.
I tried something like this:
public abstract class Aliment
{
public int Ripeness;
}
public class Fruit : Aliment
{
// be a fruit
}
public abstract class Aliments
{
public Aliments(List<Aliment> alimentList)
{
AlimentList = alimentList;
}
public List<Aliment> AlimentList { get; private set; }
public void RemoveRipe()
{
//...
}
}
public class Fruits : Aliments
{
public Fruits(List<Fruit> fruitList)
: base(fruitList)
{
}
}
The main problem is that the list of fruit cannot be converted to a list of aliments. Furthermore, the whole point of the operation is that each instance of Fruits has a List of actual Fruit (so that I can access the specific methods of Fruit). Is there any way I can do that ? Am I on a good way ?
Thanks in advance
P.S. Sorry if it is a duplicate I didn't really how to formulate the problem so as to search for it
When we say that we can't convert a List<Fruit> into a List<Aliment>, a lot depends on what we mean by "convert."
If you have a List<Fruit> and you want a List<Ailment>, you can accomplish that by creating a new list. For example, if fruitList is a List<Fruit>:
var alimentList = new List<Aliment>(fruitList.Cast<Aliment>())
Because every Fruit is an Aliment, you can cast each one of them as an Aliment and use them to populate a new List<Aliment>.
If you did that, your Fruits constructor would compile:
public class Fruits : Aliments
{
public Fruits(List<Fruit> fruitList)
: base(new List<Aliment>(fruitList.Cast<Aliment>()))
{ }
}
What we can't do is cast a List<Fruit> as a List<Aliment>.
Why? Because if we could then we could do this:
var alimentList = (List<Aliment>)fruitList;
alimentList.Add(new Vegetable());
That would not create a new list - it would simply cast the list as a different type. But if we could cast the List<Fruit> as a List<Aliment> then we could add any Aliment to the list, including a Vegetable. Then we would have a Vegetable in our List<Fruit>.
That's not always obvious to us up front, but the compiler spots it right away and prevents it.
Because of that issue, if you use the code I showed above to fix the error in the constructor you're still going to run into the exact same problem. Fruits will still have a List<Aliment> property that it inherits from Aliments, so you could still do this:
var fruits = new Fruits(someListOfFruit);
fruits.AlimentList.Add(new Vegetable());
That wouldn't give you a compiler error, but it's still obviously not the behavior you want.
What might help you is a generic class like this:
public abstract class Aliments<T> where T : Aliment
{
public Aliments(List<T> alimentList)
{
AlimentList = alimentList;
}
public List<T> AlimentList { get; private set; }
}
It allows you to do this. You can define a class that inherits from Aliments but specifies the actual type of Aliment.
public class Fruits : Aliments<Fruit>
{
public Fruits(List<Fruit> alimentList) : base(alimentList)
{
}
}
By specifying Fruit for the generic parameter T, your AlimentList property is now defined as a List<Fruit>. The compiler will only let you add Fruit to it.

Implement copy/deepcopy on multiple base classes

not sure if this maybe is a codeReview post but here we go:
My goal is to re-implement the way objects are copied within our application. We have multiple base classes:
CoreList<T> // for all list classes
BasicReference // for all reference classes
CoreObject // for all "normal" domain objects
All classes inherit from these base classes. Right now the copy method is implemented on the CoreObject class and will go through the object tree via reflection, looking at each property type and select the correct way to copy the type and finally returning always CoreObject.
There are some problems which I don't like about that approach, which is why I would like to change it:
After copying an domain object you always have to cast it "back" to the original type, for example: Animal = animal.Copy() as Animal;
All logic to copy each type is within the CoreObject class even though it should not know about other base classes.
So my first attempt was to introduce a interface:
public interface IObjectCopy<out T>
{
T Copy();
}
Which then should be implemented on all base classes. Then every class is responsible for the way it is copied. For example (pseudo code):
public class CoreObject : IObjectCopy<CoreObject>
{
public virtual GerCoreObject Copy()
{
foreach (var prop in properties)
{
if (prop.IsNoSimpleType)
{
(prop as IObjectCopy).Copy()
}
}
}
That solves the copy-responsibility problem, in addition inherited classes can take care of the copy logic themselves.
Unfortunately that does not solve the return type, I still have to cast it to the correct type. I did not think of a better solution to solve this. Any ideas?
This problem could be solved in OO using covariant return types. Unfortunately C# does not support covariant return types like Java and C++, requiring it to always break type safety.
Without breaking type safety (casting) in C# this is unfortunately not possible.
Here are two possible options:
//explicit interface implementation
public class Animal : CoreObject, IObjectCopy<Animal>
{
Animal IObjectCopy<Animal>.Copy()
{
return (Animal) base.Copy();
}
}
//does not require an explicit cast
IObjectCopy<Animal> animalCopy = myAnimal;
Animal copiedAnimal = animalCopy.Copy();
//second option: shadow the original method and cast inside the object
public class Animal : CoreObject, IObjectCopy<Animal>
{
public new Animal Copy()
{
return (Animal) base.Copy();
}
}
Animal copy = myAnimal.Copy();
Another option using bounded quantification:
public class CoreObject : IObjectCopy<CoreObject>
{
public CoreObject Copy()
{
return Copy<CoreObject>();
}
protected T Copy<T>()
where T : CoreObject, new()
{
T t = new T();
//implement copy logic:
return t;
}
}
public class Animal : CoreObject, IObjectCopy<Animal>
{
public new Animal Copy()
{
return Copy<Animal>();
}
}
If I understood it correctly, you need Curiously recurring template pattern
public class BaseClass<T> where T : BaseClass<T>
{
public virtual T Clone()
{
// Perform cloning with reflection.
return clone as T;
}
}
Then you just define your class as:
public class EndObject : BaseClass<EndObject>
{
}
EndObject e;
e.Clone() // Will return EndObject type

Implementing a collection of base classes - should I be needing this much downcasting in derived classes?

I am implementing a collection of classes that exhibit the following pattern:
public class Animal {}
public abstract class AnimalToy
{
public AnimalToy(Animal owner)
{
Owner = owner;
}
public Animal Owner { get; private set; }
/* Various methods related to all toys that use the Owner property */
}
public class Dog: Animal
{
public void Bark() {}
}
public class PlasticBone: AnimalToy
{
public PlasticBone(Dog owner) : base(owner) {}
public void Throw()
{
((Dog)Owner).Bark();
}
}
I have a base class AnimalToy with a property that is a reference to another base class Animal.
I now want to implement a Dog and a PlasticBone toy for that Dog class. PlasticBone is a toy that's only valid for dogs, and in fact the constructor restricts the owner of PlasticBone to be of type Dog.
PlasticBone has a method Throw() that is unique to that class, that uses a method on Dog (Bark()) that is unique to the Dog class. Therefore I need to cast the generic property Owner to Dog before I can access it.
This works just fine, but in the project I am working on this situation comes up again and again and leads to quite ugly code where the methods of derived classes are full of downcasts of base class references. Is this normal? Or is there a better overall design that would be cleaner?
Here's one way to fix it:
public abstract class Animal
{
public abstract void MakeNoise();
}
Let dog implement the MakeNoise and you can just call that in your Toy class:
public void Throw()
{
Owner.MakeNoise();
}
You can make AnimalToy class generic, by this you can avoid casting.
public abstract class AnimalToy<TAnimal> where TAnimal : Animal
{
public AnimalToy(TAnimal owner)
{
Owner = owner;
}
public TAnimal Owner { get; private set; }
}
public class PlasticBone: AnimalToy<Dog>
{
public PlasticBone(Dog owner) : base(owner) {}
public void Throw()
{
Owner.Bark();
}
}
Worth noting that ((Dog)Owner) is not upcast, it is called downcast. upcast is over way around.
I'm going to try to elaborate a little on the discussion in the comments and hopefully provide you with a generalised, polymorphic solution. The general idea is functionally equivalent to what Carra was suggesting but, hopefully, this will help you to apply those concepts to the domain of your actual problem.
To work with your abstraction of your problem; suppose you have your abstract base class defined like so:
public abstract class Animal
{
public abstract void Catch();
}
This is a shift in the semantics of the abstract method; you no longer have an abstract Bark method, you simply have a Catch method, the semantics of which define it as, essentially "react to something being thrown." How the Animal reacts is entirely up to the animal.
So, you'd then define Dog like so:
public class Dog : Animal
{
public override void Catch()
{
Bark();
}
public void Bark()
{
// Bark!
}
}
And change your Throw method to:
public void Throw()
{
Owner.Catch();
}
Now, Bark is specific to Dog, while the generic Catch method is universal to all Animals. The Animal class now specifies that its subclasses must implement a method that reacts to items being thrown to it. The fact that the Dog barks is entirely up to the Dog.
This is the essence of polymorphism - it's not up to the toy to determine what the dog does; it's up to the dog. All the toy needs to know is that the dog can catch it.
More generally, though, I don't like to have two classes that extend independent base classes be logically coupled (parallel hierarchies, as Eric points out) unless one of them explicitly instantiates the other, though it's impossible to offer any real advice on that without seeing your actual solution architecture.

Not sure when to use an abstract property and when not

I'm not really sure what looks better or when do I really use in abstract classes and properties, or when to use non abstract properties. I'll try to make a simple example. Let's say I have this:
abstract class Human
{
public GenderType Gender { get; set; }
public string Name { get; set; }
public Date Born { get; set; }
public bool IsNerd { get; set; }
abstract public void Speak();
abstract public void Sleep();
abstract public void AnoyingPeopleOnStackOverflow();
//... so on
}
class Peter : Human
{
//Peter is special, he got a second name
//But thats all, everything else is the same as like on other humans
public string SecondName { get; set; }
//...override abstract stuff
}
Is this alright? As I understood, I don't have to use an abstract property if I dont want to override it. And in this situation it would be ok, just the methods like Speak, Sleep and so on should be abstract.
Now, if this is ok, when would or should I use an abstract property?
Use an abstract property when you have no default implementation and when derived classes must implement it.
Use a virtual property when you have an implementation in the base class but want to allow overriding.
Use the override keyword to override a member. Mark the member as sealed override if it should not be overridden again.
Don't mark the property as abstract or virtual if you don't want it to be overridden.
Use the new keyword to hide a non-abstract, non-virtual member (this is rarely a good idea).
How to: Define Abstract Properties
I find that abstract properties often occur in a design which implies that they will have type-specific logic and/or side effects. You are basically saying, "here is a data point that all subclasses must have, but I don't know how to implement it". However, properties which contain a large amount of logic and/or cause side effects may not be desirable. This is an important consideration, though there is no fixed right/wrong way to do it.
See:
Should Properties have Side Effects
CA1024: Use properties where appropriate
Personally, I find that I use abstract methods frequently but abstract properties rarely.
I know what I want them to do, I don't care how they do it: Interface.
I know what I want them to do, I don't care how they do some of it, but I've firm ideas on how they'll (or at least most of them) do other bits: Abstract class.
I know what I want them to do, and how most of them will do it: Concrete class with virtual members.
You can have other cases such as e.g. an abstract class with no abstract members (you can't have an instance of one, but what functionality it offers, it offers completely), but they're rarer and normally come about because a particular hierarchy offers itself cleanly and blatantly to a given problem.
(Incidentally, I wouldn't think of a Peter as a type of Human, but of each peter as an instance of human who happens to be called Peter. It's not really fair to pick on example code in this way, but when you're thinking about this sort of issue it's more pertinent than usual).
Abstract members are simply virtual members that you have to override. You use this for something that has to be implemented, but can't be implemented in the base class.
If you want to make a virtual property, and want that it has to be overridden in the class that inherits your class, then you would make it an abstract property.
If you for example have an animal class, its ability to breathe would not be possible to detemine just from the information that it's an animal, but it's something that is pretty crucial:
public abstract class Animal {
public abstract bool CanBreathe { get; }
}
For a fish and a dog the implementation would be different:
public class Dog : Animal {
public override bool CanBreathe { get { return !IsUnderWater; } }
}
public class Fish : Animal {
public override bool CanBreathe { get { return IsUnderWater; } }
}
Use abstract when all sub-classes have to implement the method/property. If there's no need for each and every sub-class to implement it, then don't use it.
As for your example, if SecondName is not required for each person, then there's no need to make an abstract property in the base class. If on the other hand, every person does need a second name, then make it an abstract property.
Example of correct usage of an abstract property:
public class Car
{
public abstract string Manufacturer { get; }
}
public class Odyssey : Car
{
public override string Manufacturer
{
get
{
return "Honda";
}
}
}
public class Camry : Car
{
public override string Manufacturer
{
get
{
return "Toyota";
}
}
}
Making Maker abstract is correct because every car has a manufacturer and needs to be able to tell the user who that maker is.
An abstract property would be used where you want the class to always expose the property, but where you can't pin down the implemetation of that property - leaving it up to/forcing the inheriting class to do so.
There's an example here, where the abstract class is named Shape, and it exposes an abstract Area property. You can't implement the Area property in the base class, as the formula for area will change for each type of shape. All shapes have an area (of some sort), so all shapes should expose the property.
Your implementation itself looks just fine. Was trying to think of a sensible example of an abstract property for a Human, but couldn't think of anything reasonable.

Generic List of Generic Interfaces not allowed, any alternative approaches?

I am trying to find the right way to use a Generic List of Generic Interfaces as a variable.
Here is an example. It is probably not the best, but hopefully you will get the point:
public interface IPrimitive<T>
{
T Value { get; }
}
and then in another class, I want to be able to declare a variable that holds a list of objects that implement IPrimitive<T> for arbitrary T.
// I know this line will not compile because I do not define T
List<IPrimitive<T>> primitives = new List<IPrimitives<T>>;
primitives.Add(new Star()); // Assuming Star implements IPrimitive<X>
primitives.Add(new Sun()); // Assuming Sun implements IPrimitive<Y>
Note that the T in IPrimitive<T> could be different for each entry in the list.
Any ideas on how I could setup such a relationship? Alternative Approaches?
public interface IPrimitive
{
}
public interface IPrimitive<T> : IPrimitive
{
T Value { get; }
}
public class Star : IPrimitive<T> //must declare T here
{
}
Then you should be able to have
List<IPrimitive> primitives = new List<IPrimitive>;
primitives.Add(new Star()); // Assuming Star implements IPrimitive
primitives.Add(new Sun()); // Assuming Sun implements IPrimitive
John is correct.
Might I also suggest (if you are using C# 4) that you make your interface covariant?
public interface IPrimitive<out T>
{
T Value { get; }
}
This could save you some trouble later when you need to get things out of the list.
You say it won't work because you don't define T. So define it:
public class Holder<T>
{
public List<IPrimitive<T>> Primitives {get;set;}
}
This is one of the most complicated elements of the c# language though it is incredibly important for building well defined components. As such, c# falls short. However it is definitely possible to make this work.
The trick is to have 3 parts:
A non generic interface that contains all requirements of the interface.
A generic abstract class that implements the non generic interface and performs the type conversions as necessary.
A class that implements the generic abstract class with the appropriately typed results
For example:
public interface INonGenericInterface{
void Execute(object input);
object GetModel();
}
public abstract class IGenericInterfaceBase<T> : INonGenericInterface{
void INonGenericInterface.Execute(object input){
Execute((T) input);
}
object INonGenericInterface.GetModel(){
return GetModel();
}
protected abstract void Execute(T input);
protected abstract T GetModel();
}
public class ImplementingClass : IGenericInterfaceBase<ModelClass>{
protected override void Execute(ModelClass input){ /*Do something with the input */ }
protected override ModelClass GetModel(){ return new ModelClass();}
}
//Extras for demo
public class ModelClass { }
public class ModelClass2 { }
public class ImplementingClass2 : IGenericInterfaceBase<ModelClass2>
{
protected override void Execute(ModelClass2 input) { /*Do something with the input */ }
protected override ModelClass2 GetModel() { return new ModelClass2(); }
}
var agi = new INonGenericInterface[] { new ImplementingClass(), new ImplementingClass2() };
agi[0].Execute(); var model = agi[0].GetModel();
agi[1].Execute(); var model2 = agi[1].GetModel();
//Check the types of the model and model2 objects to see that they are appropriately typed.
This structure is incredibly useful when coordinating classes w/ one another because you're able to indicate that an implementing class will make use of multiple classes and have type checking validate that each class follows established type expectations. In addition, you might consider using an actual class instead of object for the non-generic class so that you can execute functions on the result of the various non-generic calls. Using this same design you can have those classes be generic classes w/ their own implementations and thus create incredibly complex applications.
To OP: Please consider changing the accepted answer to this to raise awareness of the correct approach as all previously stated answers fall short for various reasons and have probably left readers with more questions. This should handle all future questions related to generic classes in a collection.

Categories

Resources