Why should constructors on abstract classes be protected, not public? - c#

ReSharper suggests changing the accessibility of a public constructor in an abstract class to protected, but it does not state the rationale behind this.
Can you shed some light?

Simply because being public makes no sense in an abstract class. An abstract class by definition cannot be instantiated directly. It can only be instantiated by an instance of a derived type. Therefore the only types that should have access to a constructor are its derived types and hence protected makes much more sense than public. It more accurately describes the accessibility.

It technically makes no difference whatsoever if you make the constructor public instead of protected on an abstract class. The accessibility/visibility of the constructor is still exactly the same: the same class or derived classes. The two keywords have indistinguishable effects for all intents and purposes.
So, this choice is only a matter of style: type protected to satisfy the Object Oriented savvy people.
Reflection will by default only include the constructor when it is public, but you cannot call that constructor anyway.
IntelliSense will show the public constructor when typing new, but you cannot call that constructor anyway.
The assembly's metadata will reflect the fact that the constructor is public or protected.

It is good OO practice.
public abstract class ExampleAbstractClass
{
protected ExampleAbstractClass()
{
// :::
}
}
You only want the inheriting child classes to have access to the constructor. The only way to do that is by making the constructor protected.
Keep in mind, when you add parameters to these constructors, it is an entirely different discussion.

Related

Inheritance: only fields and methods?

Reading a book it says that the derived class inherits all fields and methods...but what about properties??
There seems to be a considerable amount of misinformation in the answers here. For the correct answer, see section 3.4 of the C# specification, which I reproduce for you here:
Members of a type are either declared in the type declaration or inherited from the base class of the type. When a type inherits from a base class, all members of the base class, except instance constructors, destructors and static constructors, become members of the derived type. The declared accessibility of a base class member does not control whether the member is inherited—inheritance extends to any member that isn’t an instance constructor, static constructor, or destructor. However, an inherited member may not be accessible in a derived type, either because of its declared accessibility or because it is hidden by a declaration in the type itself.
I have added some emphasis to the relevant part. The key is that all members are inherited except for constructors and destructors. Members are inherited regardless of whether they are methods, fields, properties, events or indexers. Members are inherited regardless of whether they are public, private or protected. Members are inherited regardless of whether they are static, instance, virtual or abstract. All members are inherited.
A derived class inherits all methods fields and, yes, properties too, although private methods, fields and properties are generally not directly accessible or visible from the derived class unless it is nested in it's superclass (the parent). Constructors and finalizers, however, are not inherited so when you derive a type you always need to code any constructors that are required for your object initialization, even if it just calls down to the base class's constructor.
However, it is generally considered good practice to make your fields private and allow access to them, if necessary, to derived classes via properties. That way it allows you, the author of the base class, to have confidence that you control the way in which the classes state (the value of it's fields) can change.
To illustrate you question about properties:
public class Person
{
public Name { get; set; }
public void Greet()
{
Console.WriteLine("Hello");
}
}
public class Child : Person
{
public Nickname { get; set;}
}
In the above example, the derived class, Child, has a nickname (a property) in addition to its derived property (Name) and its derived method (Greet).
A property is syntactic sugar for a Get_ and Set_ method.
In other words: the compiler translates a property to one or two methods. So, they're inherited as well. :)
In a word, yes, properties are inherited along with the fields and the methods. Both private and public methods, fields and properties are inherited, but private members are inaccessible by the child class (unless the child class is nested within the base class - scoping and inheritance are connected but different things).
Properties, as implemented in C# (and most other languages that support them) are just a code-level abstract for a pair of methods that get and set the property, so having a int property called Age, is syntactic sugar for a couple of methods that are called int GetAge() and SetAge(int value), so it's natural that any rules that apply to methods applies evently to properties too.

Protected Keyword C#

I want to know what is the meaning of protected in C#, why we use it, and the benefit of the keyword?
For instance
protected int currentColorIndex;
Please elaborate.
Everyone's answer is similar (a definition and/or a excerpt/link to MSDN), so ill attempt to answer your original 3 questions:
The Meaning:
Any field marked with 'protected' means it is only visible to itself and any children (classes that inherit from it). You will notice in the ASP.NET Web Forms code behind model, event handlers (such as Page_Load) are marked 'protected'. This is because the ASPX Markup file actually inherits from the code-behind file (look at the #Page directive to prove this).
Why We Use It:
The common use of the protected accessibility modifier is to give children access to it's parents properties. You might have a base class for which many subclasses derive from. This base class may have a common property. This is a good case for a protected property - to facilitate the re-use and central maintenance of common logic.
The Benefit:
Kind of similar question to "why we use it?" But essentially it gives coarse-grained control over properties. You can't just think of "when you use protected". It's more a case of choosing when to use which accessibility modifier (private, public, internal, protected). So the benefit is really the same benefit of any accessibility modifier - provide a robust and consistent object model, maximising code re-use and minimizing security risks associated with incorrectly exposed code.
Hope that helps.
As others have already pointed out:
The protected keyword is a member
access modifier. A protected member is
accessible within its class and by
derived class instances.
Here is a small example:
public class A
{
protected string SomeString;
public string SomeOtherString;
}
public class B : A
{
public string Wrapped
{
get { return this.SomeString; }
}
}
...
var a = new A();
var s = a.SomeOtherString; // valid
var s2 = a.SomeString; // Error
var b = new B();
var s3 = b.Wrapped; // valid
"A protected member is accessible from
within the class in which it is
declared, and from within any class
derived from the class that declared
this member."
see
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/protected
Straight from the MSDN:
The protected keyword is a member access modifier. A protected member is accessible within its class and by derived class instances.
Source
Using protected means you can have functionality in a class that's available to derived classes, but not to classes that just instantiate the object.
This page compares the different access modifiers and explains what they mean and gives a table of the default modifiers for different objects (enum, class, interface and struct).
Definition provided in another answer. Why is this good? You don't have to duplicate data/code from base class to its derived classes when protected offers them access to base class implementations, without the unwanted exposure to unrestricted external usage that would be implied by public.
It means that the field is only visible to the class itself and inherited classes.
Think of it like this. A class presents three interfaces:
Towards itself, with full access to internal implementation details (public, protected, private methods and attributes). By definition, anything you do in a class may affect anything else.
Towards its clients, with access only to the public methods and attributes. You minimize the public interface of a class in order to minimize unexpected consequences of changes: the less code knows about your internals, the more freely you can modify them later.
Towards its descendants, with access to the public and the protected methods and attributes. Whatever you do to protected and public methods will impact not only clients, but also descendants that modify the base functionality of your class. OO is about reducing coupling and increasing cohesion: there is no stronger coupling between classes than the inheritance relation (well, apart from the C++ friend, of course)!
The third interface is the hardest general design challenge in OO: what can reasonably be overridden (virtual methods and properties), and in order to override, what other functionality is needed (plain protected methods and attributes)? Because this is such a challenge, having classes sealed by default is actually a good idea, counterintuitive as it frequently seems to OO beginners, to whom it seems like an unnecessary handicap.

Abstract base class and constructor visibility

I usually make a base class abstract to give the signal this is a base class - you cannot instantiate me! even if there are no abstract methods in it.
Furthermore, I always make the base class constructor protected, although there's no real functional need to do that - I just want to make another point that this is a base class - you cannot instantiate me!
Am I jumping through hoops in doing that? What do you do?
It seems a reasonable thing to do, yes. There'll be no functional difference between the constructor being public or being protected, but making it protected gives a clearer indication of the intended use.
I'm not sure that you should set the class as abstract if there are no abstract methods. If it has a full implementation of the functionality that is expected of the classes derived from it, why not let it be instantiated and used as is? If this is just a way to share functionality across a range of classes then a composition based design may be more appropriate ie. have each 'derived' class reference this class rather than derive from it.
Is there a particular scenario you have in mind where this is could be an appropriate design?
Edit
The only scenario I have found where an abstract class with no abstract methods makes sense is when the abstract class is partially implementing and interface. The derived classes are required to complete the implementation.
Link to example (edit: site gone, This blog post seems to be a copy of the content)
In an abstract class, there's no difference between a public or protected constructor. As a matter of fact, I believe the compiler should give a warning or error when defining the constructor of an abstract class as public. Too bad it doesn't.

is it good design practice to only have a parameterless base class constructor?

In base class constructors I always see a parameterless constructor, like so:
public abstract BaseClass {...
protected BaseClass() { }
...}
but is it acceptable design to include a parameter in the base class constructor?
public abstract BaseClass {...
protected BaseClass(string initObj) { }
...}
Yes, it is acceptable for a base class to require a parameterized constructor. This simply imposes a requirement that any classes which inherit must provide a value to the base constructor.
In most cases the derived classes have some form of parameterized constructors.
So when those constructors are called they can still call the parameterless base constructor:
public employee(int age) : base(this)
The answer is if you need one just add one, there is nothing wrong with that. Think of a business object base class that requires some validations to say a phone number or email address. You want to ensure the derived classes get these business rules loaded into them. If you did not have the base class constructor you could not add these rules to your derived class objects.
It is a good practice if the object cannot be used or has dependencies on every method on this class. For instance, if you have a class that have the same parameters in all the functions, it would be better to set that in the constructor, so the function signature is smaller.
What the writer of the base class is doing in your first example is just making sure that no public constructors are exposed. Probably the base class needs nothing special in the constructor but, if you don't write any, the compiler will add the default (parameter-less) constructor for you.
Not that I think this is specially useful. You cannot instantiate an abstract class anyway.
It is certaibly acceptable. Whether is is needed or useful depends entirely on the (design of) the classes.
Yes, its a perfectly acceptable design decision, only it must make sense for the base class - presumably to initialise its own members from the parameter. Also, it imposes a restriction on derived classes: either they must pass in a literal, or impose a similar restriction on their clients or further derived classes.

Automatically making Base Constructors available in derived class?

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. :-(

Categories

Resources