I'm guessing there's something really basic about C# inheritance that I don't understand. Would someone please enlighten me?
Sometimes, when subclassing, you want to restrict the conditions required to create an instance of the class.
Let me give you an example. If classes did inherit their superclass constructors, all classes would have the parameterless constructor from Object. Obviously that's not correct.
If you think about what would happen if constructors were inherited, you should start to see the problem.
As nearly every type in .NET inherits from Object (which has a parameterless constructor), that means almost every type that you create would be forced to have a parameterless constructor. But there are many types where a parameterless constructor doesn't make sense.
There would also be a problem with versioning. If a new version of your base type appears with a new constructor, you would automatically get a new constructor in your derived type. This would be a bad thing, and a specific instance of the fragile base class problem.
There's also a more philosophical argument. Inheritance is about type responsibilities (this is what I do). Constructors are about type collaboration (this is what I need). So inheriting constructors would be mixing type responsibility with type collaboration, whereas those two concepts should really remain separate.
Constructors in superclasses are called, whether you explicitly call them or not. They chain from the parent class down. If your constructor doesn't explicitly call a constructor in it's superclass then the default constructor in that class is called implicitly before the code of your constructor.
I assume you mean:
class Foo
{
public Foo(int someVar) {}
}
class Bar : Foo
{
// Why does Bar not automatically have compiler generated version of
Bar(int someVar): Foo(someVar) {}
}
I believe this is inherited from C++ (and Java).
But assuming you did have this and Bar had some other member variables. Would this not introduce the posability of the compiler generated constructor accdently being used and not initialising the members of BAr.
The default constructor will always be called .
class Bar : Foo { }
When Bar is instantiated it will call the Foo() constructor by default.
class Foo {
public Foo(int someVar) {}
}
class Bar : Foo {
public Bar() : base(42) {}
}
If there is not parameterless constructor you will be required to define which one to use and pass the parameters.
Related
I have a base class Character which has several classes deriving from it. The base class has various fields and methods.
All of my derived classes use the same base class constructor, but if I don't redefine the constructor in my derived classes I get the error:
Error: Class "child class" doesn't contain a constructor which takes this number of arguments
I don't want to redefine the constructor in every derived class because if the constructor changes, I have to change it in every single class which, forgive any misunderstanding, goes against the idea of only writing code once?
You can use the following syntax to call the base class constructor from the classes that derive from it:
public DerivedClass() : base() {
// Do additional work here otherwise you can leave it empty
}
This will call the base constructor first, then it will perform any additional statements, if any, in this derived constructor.
Note that if the base constructor takes arguments you can do this:
public DerivedClass(int parameter1, string parameter2)
: base(parameter1, parameter2) {
// DerivedClass parameter types have to match base class types
// Do additional work here otherwise you can leave it empty
}
You can find more information about constructors in the following page:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-constructors
In a derived class, if a base-class constructor is not called explicitly by using the base keyword, the default constructor, if there is one, is called implicitly.
You do have to redeclare constructors, because they're effectively not inherited. It makes sense if you think of constructors as being a bit like static methods in some respects.
In particular, you wouldn't want all constructors to be automatically inherited - after all, that would mean that every class would have a parameterless constructor, as object itself does.
If you just want to call the base class constructor though, you don't need to write any code in the body of the constructor - just pass the arguments up to the base class as per Waleed's post.
If your base class starts requiring more information, it's natural that you should have to change all derived classes - and indeed anything calling the constructors of those classes - because they have to provide the information. I know it can seem like a pain, but it's just a natural consequence of what constructors do.
I had the same problem, and I solved it by replacing my constructor with a factory method like this:
A is the parent class.
public static T getChild<T>(int number) where T:A, new()
{
T child = new T();
T._number = number;
return child;
}
You can create a Child class with
Child b = A.getChild<Child>(2);
A kind of alternative could be to rely on a Dependency Injection container to initialize your objects, that way the that reference to the base class (could be the call to the base constructor or another initializer method) would "externalized" to the DI container.
I don't know if it makes sense to your case or not
I know we cannot create an abstract class instance, but I cannot understand why could use base invoke the constructor of the abstract class.
abstract class Fruit
{
public string Name { get; private set; }
public Fruit(string name)
{
Name = name;
}
}
class Apple : Fruit
{
public Apple(string name) : base(name) { }
}
Fruit f = new Fruit("Fruit"); // Coimple Error
Apple a = new Apple("Apple"); // Success
Dose that base keyword just invoke constructors, methods, etc?
What's the differences between create an instance and invoke a constructor?
Thanks in advance.
Only derived class (e.g. Apple) can call the constructor of its parent (abstract class) with special base word. Constructor cannot be invoked (called) directly.
I would add that the fact that an abstract class may provide a constructor doesn't mean that it's not yet abstract.
By definition, an abstract class is a class where some or none of its members don't provide a default implementation, and derived classes must provide an implementation to these members. In the other hand, since an abstract class has some of its members as just signatures - the whole abstract members -, code mustn't be able to instantiate that class.
But if a derived class - either abstract or concrete - couldn't be able to call a base abstract class constructor, abstract classes would lack polymorphic constructors and there may be no way to initialize class properties or define a default class initialization code, even if that code calls an abstract method or property.
This is why a derived class can call a parent class constructor, even if the class is abstract!
What's the differences between create an instance and invoke a
constructor?
We might try to address this question with a deep explanation with low-level details, but
I feel that it's more a conceptual issue rather than a low-level thing.
If you want a summary, calling the constructor is a part of class instantiation process. It's a method which is called once the instance has been created and initializes the instances with custom code before any other code might use that instance.
When you use base keyword in a constructor to call parent's class one, you're just chaining constructor calls from the most derived class to the base class.
Does that base keyword just invoke constructors, methods, etc?
No, use it anytime you want to explicitly invoke the parent class' methods and avoid invoking a override in the derived class. Though : base(...) syntax is exclusive to constructors, usually you would call base.method();
What are the differences between create an instance and invoke a constructor?
Creating an instance with the new operator does a number of things:
Allocates memory for the object
Initialises fields
Then finally the constructor is invoked, which will invoke base constructor first if specified.
A more in-depth explanation of the order is in this answer: https://stackoverflow.com/a/1882778/360211 but that should be enough to explain the difference.
Creating an instance with the new keyword creates a new object and returns a reference to the object.Invoking the constructor with the base keyword won't create a reference to the object(neither it will create an actual object), it will simply execute the code in the constructor.
Take a deep look onto this answer to for more information https://stackoverflow.com/a/14453366/3789232
Do we have any advantage or is it just tradition to call base class constructor like #1,
do both #1 and #2 differ? (I have used #2 when I happen to have overloading constructor for BaseClass, but why we ).
public class BaseClass
{
public BaseClass()
{
Console.WriteLine("From Base");
}
}
#1
public class DerivedClass
: BaseClass
{
public DerivedClass()
:base()
{
Console.WriteLine("From Derived");
}
}
#2
public class DerivedClass
: BaseClass
{
public DerivedClass()
{
Console.WriteLine("From Derived");
}
}
No, there is no difference. In case #2, the compiler will generate the call to the base class constructor (if there is a parameterless base class constructor available, that is). Adding such a call manually is a style question. It is only compulsory when there is no parameterless base class constructor available, so the compiler can't decide itself how to call it.
They're basically the same. The parameterless constructor of the base class gets called implicitly if you don't specify anything.
That's also why #2 would give you an error if the base class didn't have a parameterless constructor. (#1 would, too, but the fact that #2 gives you an error tells you that it tries to call a parameterless base constructor even if you don't specify the call to it)
As a rule, I generally use #1 if the derived class specifically needs the base class's constructor to run before it. In reality there's no difference to the compiler, but it makes it clearer that there's a dependency. This can be very relevant if you ever consider porting to other platforms. In Delphi for example, a constructor will not call the base class' constructor unless you specifically tell it to; if I were porting the code to Delphi, I'd be more likely to remember to do that with #1.
For example if the base class instantiates a list, and the derived adds to it, I'd use #1. If the derived constructor simply initialises a local field, I'd use #2.
There is no difference. The reason why : base() syntax exists is so that you can call a non-default constructor (with parameters). It would feel arbitrary if the default constructor could not be called the same way.
How can I prevent inheritance of some methods or properties in derived classes?!
public class BaseClass : Collection
{
//Some operations...
//Should not let derived classes inherit 'Add' method.
}
public class DerivedClass : BaseClass
{
public void DoSomething(int Item)
{
this.Add(Item); // Error: No such method should exist...
}
}
The pattern you want is composition ("Has-a"), not inheritance ("Is-a"). BaseClass should contain a collection, not inherit from collection. BaseClass can then selectively choose what methods or properties to expose on its interface. Most of those may just be passthroughs that call the equivalent methods on the internal collection.
Marking things private in the child classes won't work, because anyone with a base type variable (Collection x = new DerivedClass()) will still be able to access the "hidden" members through the base type.
If "Is-a" vs "Has-a" doesn't click for you, think of it in terms of parents vs friends. You can't choose your parents and can't remove them from your DNA, but you can choose who you associate with.
You can't, in this instance inheritance is the wrong tool for the job. Your class needs to have the collection as a private member, then you can expose as much or as little of it as you wish.
Trying to hide a public member of a class in a derived class is generally a bad thing(*). Trying to hide it as a means of ensuring it won't be called is even worse, and generally won't work anyhow.
There isn't any standardized idiomatic means I know of to prevent a parent class' protected member from being accessed in a sub-derived type, but declaring a new public useless member of a clearly-useless kind would be one approach. The simplest such thing would be an empty class. For example, if class Foo declares an empty public class called MemberwiseClone, derivatives of Foo will be unable to call MemberwiseClone--probably a good thing if MemberwiseClone would break the invariants of class Foo.
(*) The only situation where it is appropriate is when a public method of a derived class returns a more specialized type than the corresponding method in the base class (e.g. a CarFactory.Produce() method may return a Car, while the FordExplorerFactory.Produce() method may return a FordExplorer (which derives from car). Someone who calls Produce() on what they think is a CarFactory (but happens to be a FordExplorerFactory) will get a Car (which happens to be a FordExplorer), but someone who calls Produce() on what is known at compile time to be a FordExplorerFactory will get a result that's known at compile time to be a FordExplorer.
I have a Base Class with two constructors, requiring a parameter:
public abstract class StoreBase
{
private readonly SomeObject_sobj;
protected StoreBase(SomeObject sobj)
{
_sobj = sobj;
}
protected StoreBase(OtherObject oobj)
{
_sobj = new SomeObject(oobj);
}
}
Then I have a derived class:
public class MyDerived: StoreBase
{
}
This causes a compilation error as base class doesn't contain parameterless constructor.
My understanding is that because MyDerived doesn't contain a constructor, the compiler adds a parameterless constructor (that's well known and nothing to do with derived classes). However, as it derives from another class, the base class constructor needs to run first, and there is no way to determine which constructor should run from the empty MyDerived constructor.
Basically I'm asking: can I avoid copy/pasting all constructors from Base into Derived class if I really don't need additional constructor logic? Can I say "Take all constructors from base" without adding them all?
(And yes, I know I could/should refactor this into a parameterless constructor and a protected virtual Initialize() method. but I still wonder if I can work with constructors and still avoid copy/paste)
No - you will need to implement the (appropriate) constructors in the derived class, as well.
The derived class only needs to use one of the base constructors - so the constructors required in it may be completely different than the base class. They will need to be implemented by hand, even if that's just:
public class MyDerived : StoreBase
{
public MyDerived(SomeObject sobj) : base(sobj) {}
public MyDerived(OtherObject oobj) : base(oobj) {}
}
Also:
(And yes, I know I could/should refactor this into a parameterless constructor and a protected virtual Initialize() method. but I still wonder if I can work with constructors and still avoid copy/paste)
Although I see this touted, I believe this is not always a good practice. In many cases, this is actually problematic, as you're relying on the subclass to properly call Initialize if they override your protected virtual method. For example, if the subclass did this, it could potentially be very bad:
public class MyDerived : StoreBase
{
// .. other stuff
protected override void Initialize()
{
// Leave out, intentionally or accidentally, the following:
// base.Initialize();
}
}
I actually avoid this in most situations, and initialize in the constructors (or in a private, non-virtual initialize method). Not doing this breaks any guarantees you have that your initialization will always occur the way you intend.
Constructors and constructor chaining provide the same functionality, with much better guarantees.
No, constructors are not inherited, and there is no shortcut for creating copies of the base constructors.
The closest is to implement constructors that call the base constructors. I guess you want to make them public anyway, so that you can actually create an instance of the class:
public MyDerived(SomeObject sobj) : base(sobj) {}
public MyDerived(OtherObject oobj) : base(oobj) {}
The compiler will only generate a default (parameterless) constructor if you haven't provided any constructor yourself. Once you define a constructor, the compiler won't generate one for you.
This can be important to keep in mind if you plan on serializing your class since serialization requires a default constructor. If your give your class a constructor other than a default one, then you'll also need to provide a default one to support serialization because, again, once you provide any constructor, the compiler won't provide one for you automatically.
Unfortunately the answer is no.
One thing you can do is call base from your MyDerived constructor:
class MyDerived: StoreBase
{
public MyDerived(OtherObject obj) : base (obj) {}
}
Can I say "Take all constructors from base" without adding them all?
No. :-(