It is an important and popular fact that properties in C# can be defined in interfaces. For example:
public interface IThing { IThing Parent { get; } }
We can then implement that interface on a concrete class:
public class : Thing { public IThing Parent { get { /* return a parent from somewhere */ } } }
Like so. We can also use the nifty new syntax to implement the property to be just like a simple field:
public IThing Parent { get; set; }
Notice (this is the crucial point) that this defines a setter as well as a getter for the property. It doesn't make any difference to clients of IThing, because they only need a getter, but it might be useful for clients of Thing. Very nice.
Now I know what you're thinking. Nobody British writes a blog post like this about a language feature unless some aspect of it is unsatisfactory. So here it comes.
Suppose I want to follow the same pattern but using an abstract class instead of an interface. It's basically the same idea:
public abstract class IThing { public abstract IThing Parent { get; } }
The only difference in the concrete derived class is the need to use the modifier override:
public class Thing : IThing { public override IThing Parent { get { /* blah */ } } }
But there's another difference, can you guess it?
public class Thing : IThing { public override IThing Parent { get; set; } }
The above produces an error: cannot override because 'IThing.Parent' does not have an overridable set accessor.
It's the same if you try to write the getter and setter in long hand. You are banned from providing a setter, even though it makes no difference to the correctness of your implementation of IThing.
I can just hear the language designers saying wisely to themselves, "Why the heck would anyone ever want to override the getter but not the setter, or vice versa for that matter?" Well, now you know, you crazy old language designers.
If the base class has an abstract getter but no setter (or vice versa) it ought to be a perfectly valid thing to override that getter (or setter) while also providing a non-virtual matching setter (or getter).
To fix this, we need the ability to apply the override modifier on the getter and setter individually.
3 comments:
So true. I'm having the same problem here. That problem doesn't exist in Java. Guess who's the copy of who?
It always amused me that in the introduction of the C# specification, they omitted Java from the list of languages that it was inspired by (but mentioned C++). And Java omitted C++ in its introduction (but mentioned Smalltalk). And C++ omitted Smalltalk (but mentioned Simula). And if Smalltalk ever had a specification, I bet it omitted to mention Simula (but mentioned Lisp). They each fail to mention the best known predecessor in the space they trying to move into.
These days the question of who copied who in Java and C# is more complicated. C# had properties as a language feature before Java started considering it, and so it would be surprising if Java's version wasn't a little better.
So true..
Post a Comment