I am new to C#, and are trying to understand classes and "is a" relationships. I've been trying to get a piece of code to work, but I can't seem to get it right.
It looks like this: http://pastebin.com/cQDusptB
I have a base class, Mammal, which one should be able to create instances of, giving the name of the mammal as input.
I also have a class, Dog, which is a Mammal. One should be able to create an instance of this too, in the same manner as Mammal.
Can anyone see my flaw(s)? If yes, can you please explain what i misunderstood/forgot?
When posting questions like this it is helpful to also post the error message the compiler gave you.
Can anyone see my flaw(s)?
You have a virtual constructor.
can you please explain what i misunderstood/forgot?
Constructors are not inherited in C# and therefore it makes no sense to mark them as either virtual or override.
The constructor of Dog needs to be named "Dog". You can't/don't need to override "Mammal". Also, Mammal's constructor shouldn't be virtual.
public class Mammal
{
public Mammal(string name)
{
//....
}
}
public class Dog : Mammal {
public Dog(string name) : base(name)
{
}
}
You pass arguments to the base class constructor using the "base" keyword (see code above).
Be sure to pick up a good book on C# to get the language basics right.
You have a few issues here. For one, constructors can not be marked as virtual or overridden. Another problem is that you attempt to call the method .Name without parentheses. The corrected version looks like this:
public class Mammal
{
protected string _Name;
public virtual string Name()
{
return (this._Name + " - of type " + this.GetType());
}
public Mammal(string Name)
{
this._Name = Name;
}
}
public class Dog : Mammal
{
public Dog(string Name) : base(Name)
{
}
public override string Name()
{
return (base._Name + "Dog");
}
}
static void Main()
{
Mammal AnimalA = new Mammal("SubjectA");
Console.WriteLine("{0}", AnimalA.Name());
Mammal AnimalB = new Dog("SubjectB");
Console.WriteLine("{0}", AnimalB.Name());
Console.ReadLine();
}
Constructors are not inherited/overridden.
Lose the 'virtual' keyword from the Mammal constructor in the Mammal class.
Remove the Mammal ctor override attempt in the Dog class.
Replace it with a Dog constructor that calls the Mammal one (like this):
public Dog(string name) : base(name)
{
}
Now when a dog is constructed it will call through to the mammal base class constructor passing the specified name.
Related
I have an Animal class, and two derived classes: Lion and Ant.
I have a method that takes in an Animal type and I want to return a new instance of the derived type of the animal passed to the function (i.e. a new instance of Lion).
public Animal Reproduce(Animal p_animal)
{
Type animalType = p_animal.GetType();
if (SameSpecies(p_animal))
return new animalType(RandomName());
}
There are several ways to achieve this, but what I would suggest is that you create an abstract Reproduce method on your Animal class and implement it in the derived types. For instance:
public abstract class Animal
{
/* .. other stuff .. */
public abstract Animal Reproduce();
public string RandomName() { /* ... */ }
}
public class Lion : Animal
{
/*... other stuff .. */
public override Animal Reproduce() => new Lion(RandomName());
}
That way you can add any future logic in the Reproduce method specific to a certain Animal
Since you don't know the type at compile time, you will have to use Reflection. What you are trying to achieve can be done with:
return (Animal)Activator.CreateInstance(animalType, RandomName());
That line is executed at runtime, meaning that, if the type "animalType" is actually not an extension of the class "Animal", this line will fail at runtime. Also, one of the constructors of your type "animalType" needs to receive exactly one argument of whatever type "RandomName()" function returns, otherwise you will also have a runtime error.
EDIT: Reflection has a performance cost and should be avoided when possible. KMoussa suggested a good approach you can follow that avoids reflection and thus is much better than the reflection approach.
You could use reflection OR you could keep some type safety and use something called the 'Curiously recurring template pattern'. It uses generics, if you aren't familiar with that concept, I would do some reading up as they are very powerful, useful and prevalent in the .Net Eco system. Any way, here is what I would do
public abstract class Animal<T>
where T : Animal<T>
{
public string Name {get; private set;}
public Animal(string name)
{
Name = name;
}
public abstract T Reproduce();
public static T Reproduce(T animalToReproduce)
{
return animalToReproduce.Reproduce();
}
}
public class Lion : Animal<Lion>
{
public Lion(string name)
: base (name)
{
}
public override Lion Reproduce()
{
return new Lion(RandomName());
}
}
Then you can just call Animal.Reproduce(yourAnimalInstance)
this will return an object of the correct type. For example
Lion myLion = GetALionFromSomewhere();
Lion babyLion = Animal.Reproduce(myLion);
That will compile and you've got all the goodness of type safety
I have a base class with a method that can be overridden. If I inherit a class from this base class how can I make the method return the inherited type?
Like:
public class ClassA : BaseClass
{
public override ClassA TestMethod(...)
{
// ...
}
}
Do I need to provide a type manually to the base class ? Or can I make it provide that type automatically?
You could use a generic type to do it.
public class BaseClass<T> where T : BaseClass<T> {
public abstract T TestMethod(...);
}
public class ClassA : BaseClass<ClassA>
{
public override ClassA TestMethod(...)
{
// ...
}
}
Why do you need it? Might lead to better suiting answers...
The feature you want has a name; this is return type covariance.
The reasons it is not supported in C# are here:
Why C# doesn't allow inheritance of return type when implementing an Interface
The other answers are all suggesting that you use the C# version of the curiously recurring template pattern to solve your problem. My opinion is that the pattern makes more problems than it solves. See my article on that subject for more details:
http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx
A better way to solve this problem is to use this pattern:
abstract class Animal
{
protected abstract Animal ProtectedGetMother();
public Animal GetMother()
{
return this.ProtectedGetMother();
}
}
class Cat : Animal
{
protected override Animal ProtectedGetMother()
{
do the work particular to cats here
make sure you return a Cat
}
public new Cat GetMother()
{
return (Cat)this.ProtectedGetMother();
}
}
The problem is that you cannot override a virtual method with a different return type. So don't. Make a brand new method with a different return type and make the virtual method an implementation detail of the class hierarchy.
This technique is approximately one billion times easier to understand than this Cat : Animal<Cat> "a cat is an animal of cat" nonsense.
You can do this in a generic way:
public abstract class Base
{
public abstract T AbstractTestMethod<T>() where T : Base;
public virtual T VirtualTestMethod<T>() where T : Base, new()
{
return new T();
}
}
public class ClassA : Base
{
public override ClassA AbstractTestMethod<ClassA>()
{
return new ClassA();
}
public override ClassA VirtualTestMethod<ClassA>()
{
return new ClassA();
}
}
Using virtual methods behaves not as strict as using abstract methods. Using the abstract way you can force developers to implement the method on their own. Using the virtual way you can tell them something like "meet my constraints and feel free to use the default behaviour".
I have a class that extends to Control:
public foo : Control
{
//..
}
And then I get a control:
var baa = (((foo)((Control)Controls.Find(controlName, true).First()));
baa.etc = ..;
But when I do:
((PictureBox)((Control)controlImg)).MyExtensionMethod(..)
I get an exception:
Unable to cast object of type 'System.Windows.Forms.PictureBox' to type 'ControlExtensions.foo'.
How to fix this exception and let me know.
Thank you.
There is no way to fix this. You class foo is correct. The error message explains it all. foo does not inherit PictureBox. If foo is a picture box of some sort, implement the PictureBox class and not Control.
To give you a real life example:
interface IAnimal { }
class Dog : IAnimal { public static void Bark() { } }
class Cat : IAnimal { public static void Meow() { } }
The signature of Cat is different than Dog as Cat defines Cat.Meow(), whereas Dog does not. Dog defines Dog.Bark(), whereas Cat does not. For example, the following code with comments will help you wrap your head around this:
class Program
{
static void Main(string[] args)
{
Dog myDog = new Dog(); // myDog contains definition for Bark
IAnimal myPet = (IAnimal)myDog; // Cast not necessary.
// myPet's signiature is of Dog, but typeof(myPet)
// is Animal as it was boxed (google for help on this)
Cat myCat = (Cat)myPet // now try and imagine this in real life
// (turning a dog into a cat) [I don't even]
// It doesn't work because Cat doesn't
// contain a definition for Bark()
Cat myDimentedCat = (Cat)(IAnimal)myDog; // which is why this code fails.
}
}
What I am trying to show is the same thing as a square is a rectangle, but a rectangle isn't always a square:
interface IRectangle { }
interface ISquare : IRectangle { }
Both Anthony in the comment and Cole in his answer showed you where the exception come from. As to how fix it, I'm not sure if I got exactly what you intend to do, but looking at the name of the method you are trying to call, and at the fact that you say that foo "extends" Control, it seems to me that you are trying to extend the behaviour of windows form controls adding some MyExtensionMethod. If this is the case, you should not create a foo class derived from Control, but a static class containing the extension methods you need. I.e. your code should look like this:
public static class SomeControlExtensions
{
public static int MyExtensionMethod(this Control aCtl)
{
// whatever you want
}
}
An extension method has always at least an argument that represent the receiver of the message. This is identified by the keyword "this" before the type of the argument. In this way you will be able to compile this:
Control baa = (Control)Controls.Find(controlName, true).First();
baa.MyExtensionMethod();
Ok... in Objective C you can new up a subclass from a static method in the base class with 'new this()' because in a static method, 'this' refers to the class, not the instance. That was a pretty damn cool find when I first found it and I've used it often.
However, in C# that doesn't work. Damn!
So... anyone know how I can 'new' up a subclass from within a static base class method?
Something like this...
public class MyBaseClass{
string name;
public static Object GimmeOne(string name){
// What would I replace 'this' with in C#?
return new this(name);
}
public MyBaseClass(string name){
this.name = name;
}
}
// No need to write redundant constructors
public class SubClass1 : MyBaseClass{ }
public class SubClass2 : MyBaseClass{ }
public class SubClass3 : MyBaseClass{ }
SubClass1 foo = SubClass1.GimmeOne("I am Foo");
And yes, I know I can (and normally would) just use the constructors directly, but we have a specific need to call a shared member on the base class so that's why I'm asking. Again, Objective C let's me do this. Hoping C# does too.
So... any takers?
C# doesn't have any exact equivalent to that. However, you could potentially get around this by using generic type constraints like this:
public class MyBaseClass
{
public string Name { get; private set; }
public static T GimmeOne<T>(string name) where T : MyBaseClass, new()
{
return new T() { Name = name };
}
protected MyBaseClass()
{
}
protected MyBaseClass(string name)
{
this.Name = name;
}
}
The new() constraint says there is a parameterless constructor - which your didn't but we make it private to hide that from consumers. Then it could be invoked like this:
var foo = SubClass1.GimmeOne<SubClass1>("I am Foo");
Sorry, you can't do this. C# is morally opposed to static method inheritance. That GimmeOne method will never have any type other than MyBaseClass, and calling it from SubClass1 doesn't matter- it's still "really" a MyBaseClass call. The Reflection libraries could do this construction, but you'd never get anything other than a MyBaseClass out of it.
If you're calling a static method, presumably you know which subclass you're calling it from. Create a different factory method for each subclass. If you're actually trying to do this by instance, you should probably use a non-static virtual factory method (which will automatically call the most derived form of the function, which is probably what you want) instead.
Does code in the constructor add to code in subclass constructors? Or does the subclass's constructor override the superclass? Given this example superclass constructor:
class Car{
function Car(speed:int){
trace("CAR speed "+speed)
}
}
...and this subclass constructor:
class FordCar extends Car{
function FordCar(model:string){
trace("FORD model "+model)
}
}
When an instance of FordCar is created, will this trace "Car" and "Ford" ??
Edit: Will arguments also add up? See updated code above.
Yes. In most languages, the base class constructor is executed, then the subclasses constructor. This will make it trace: "CAR", then "FORD".
Both class constructors should always execute if you construct an instance of the subclass. Depending on the language in question, the actual execution and choice of base class constructor, including ordering, may be different. (This is particularly true in languages which allow for multiple inheritance - as the order of execution can be difficult to determine at first glance in some cases.)
Edit:
In most languages, your edited code will not compile. The subclass typically needs to pass arguments of the same type to the base class constructors. This is language specific, but often looks something like:
function FordCar(model: string) : Car(42) {
In some languages (mainly dynamic languages), the language will try to automatically convert, but you often may still need to specify which of the parent constructors to call.
Often, you can do:
function FordCar(int: speed, model: string) : Car(speed) {
trace("FORD model " + model)
}
Yes, it will trace both. Usually your child class's constructors will have to call your base class's constructor. If more than one base class constructor is given, then you may have options. However, if only one is given, then you MUST satisfy its requirements.
Consider the following code and pay particular attention to the various constructors and how they work with the superclass's constructors:
public interface IAnimal
{
string GetName();
string Talk();
}
public abstract class AnimalBase : IAnimal
{
private string _name;
// Constructor #1
protected AnimalBase(string name)
{
_name = name;
}
// Constructor #2
protected AnimalBase(string name, bool isCutsey)
{
if (isCutsey)
{
// Change "Fluffy" into "Fluffy-poo"
_name = name + "-poo";
}
}
// GetName implemention from IAnimal.
// In C#, "virtual" means "Let the child class override this if it wants to but is not required to"
public virtual string GetName()
{
return _name;
}
// Talk "implementation" from IAnimal.
// In C#, "abstract" means "require our child classes to override this and provide the implementation".
// Since our base class forces child classes to provide the implementation, this takes care of the IAnimal implementation requirement.
abstract public string Talk();
}
public class Dog : AnimalBase
{
// This constructor simply passes on the name parameter to the base class's constructor.
public Dog(string name)
: base(name)
{
}
// This constructor passes on both parameters to the base class's constructor.
public Dog(string name, bool isCutsey)
: base(name, isCutsey)
{
}
// Override the base class's Talk() function here, and this satisfy's AnimalBase's requirement to provide this implementation for IAnimal.
public override string Talk()
{
return "Woof! Woof!";
}
}
public class SmallDog : Dog
{
private bool _isPurseDog;
// This constructor is unique from all of the other constructors.
// Rather than the second boolean representing the "isCutsey" property, it's entirely different.
// It's entirely a coincidence that they're the same datatype - this is not important.
// Notice that we're saying ALL SmallDogs are cutsey by passing a hardcoded true into the base class's (Dog) second parameter of the constructor.
public SmallDog(string name, bool isPurseDog)
: base(name, true)
{
_isPurseDog = isPurseDog;
}
// This tells us if the dog fits in a purse.
public bool DoesThisDogFitInAPurse()
{
return _isPurseDog;
}
// Rather than using Dog's Talk() implementation, we're changing this because this special type of dog is different.
public override string Talk()
{
return "Yip! Yip!";
}
}
public class Chihuahua : SmallDog
{
private int _hatSize;
// We say that Chihuahua's always fit in a purse. Nothing else different about them, though.
public Chihuahua(string name, int hatSize)
: base(name, true)
{
_hatSize = hatSize;
}
// Of course all chihuahuas wear Mexican hats, so let's make sure we know its hat size!
public int GetHatSize()
{
return _hatSize;
}
}
public class Cat : AnimalBase
{
// This constructor simply passes on the name parameter to the base class's constructor.
public Cat(string name)
: base(name)
{
}
// This constructor passes on both parameters to the base class's constructor.
public Cat(string name, bool isCutsey)
: base(name, isCutsey)
{
}
// Override the base class's Talk() function here, and this satisfy's AnimalBase's requirement to provide this implementation for IAnimal.
public override string Talk()
{
return "Meoooowwww...";
}
}
public class Lion : Cat
{
public Lion(string name)
: base(name)
{
}
// Rather than using Cat's Talk() implementation, we're changing this because this special type of cat is different.
public override string Talk()
{
return "ROAR!!!!!!!!";
}
}
[edit]
Your code that you added will usually not compile. The subclass's constructor usually MUST provide all parameters to the superclass's constructor. Not providing them is not an option. See my code to see how my subclass constructors provide the parameters to the superclass constructors. Sometimes they just pass on the parameters and other times they actually put hard-coded true/false values in.
Constructors in C# (and most languages) are not inherited and cannot be overriden. However if the constructor does not explicitly call a base constructor an implicit call is made to the default constructor of the base class.
Just to confirm not all languages are alike: in Python, the default behaviour is the replacement of the superclass constructor.
class Car():
def __init__(self, speed):
print "speed", speed
self.speed = speed
class FordCar(Car):
def __init__(self, model):
print "model", model
self.speed = 180
self.model = model
>>> FordCar("Mustang")
model Mustang
This is, imvho, sensible because Python allows multiple inheritance.