I have two questions regarding the use of an abstract class on left side of object instantiation.
AbstractClass MyClass = new ConcreteClass();
1 - What is this called? (when you declare the abstract class on the left.)
e.g.
Car MyNiceCar = new NiceCar();
I know this relates to Polymorphism, but I'm specifically asking how to describe/verbalize the scenario when declare the abstract class on the left.
2 - And why do it? i.e. Why would you do:
Car MyNiceCar = new NiceCar();
And not:
NiceCar MyNiceCar = new NiceCar();
?
Would the answer to question 2 possibly be so that i can do the following?
Car MyNiceCar = new NiceCar();
.
. //do some logic to decide if I can have a nicer car.
.
MyNiceCar = new EvenNicerCar();
1) You're creating a base class reference to your Derived class.
Edit:
Other words for BaseClass: SuperClass, ParentClass
Other words for DerivedClass: SubClass, ChildClass
Don't ask why there are so many words for each. It's kinda a Spaces vs Tabs type thing.
2) You do it so that you can use virtual functions/properties that you know all the derived classes will have. You want to do something that a Car can do, and you don't care if its a CrapCar, NiceCar or SuperNiceCar
Car car = new MyNiceCar();
car.honk(); //meep!
car = new SuperNiceCar();
car.honk(); //beep beep!
However, you can't go the other way around.
SuperNiceCar may support UseTurbo(), but MyNiceCar does not.
But you don't care, you just want the car to honk, so you cast it as a Car, because you know all Cars can honk.
See also
1 - What is this called?
This is a type of polymorphism that's called "inclusion polymorphism". It allows you to create restrictions on the type of variable that can be used in your code, while still allowing some type flexibility. Java and C#, for instance, have generics that allow various types and references to use the same code. However, these often run into run-time issues that could otherwise be caught by a static code analyzer. It's generally considered to be less risky to rely on the static analyzer (assuming your IDE has a good one) than to wait and find out your code has bugs in it after your release.
2 - And Why do it?
In addition to the reason I gave above, one of the most common applications of this is the polymorphic array.
Consider the following:
// Both classes contain an Accelerate() function
NiceCar MyNiceCar = new NiceCar();
EvenNicerCar MyEvenNicerCar = new EvenNicerCar();
// We're forced to use these methods separately
MyNiceCar.Accelerate();
MyEvenNicerCar.Accelerate();
////////////////////////////////////////////////////////////////////////////////////////////////////
// We can make this code much smaller and less prone to copy/paste errors using polymorphism!
Car[] MyPolymorphicArray = new Car[] { new NiceCar(), new EvenNicerCar() };
foreach(c in MyPolymorphicArray) { c.Accelerate(); }
Using this type of syntax, you can see that I'm able to make the code smaller, more-manageable, type-safe, and our static code analyzer will complain if we get it wrong, rather than waiting until runtime to find out. When you use this type of architecture, make sure you require the methods intended to be used by the instances to either be in an interface or in the parent class of that object in order to help avoid implementation errors. Additionally, take note that if you do this, the Accelerate() method may only need to be written in the parent class, which helps make the code even smaller.
Following on from two excellent answers from #Mars and #chris-mauer which both answered Question 2 of my post perfectly. And allowed me to study this concept further.
I want to include that the answer to Question 1 of my post as follows. I asked:
AbstractClass MyClass = new ConcreteClass();
1 - What is this called? (when you declare the abstract class on the left.)
From the article below, I believe the correct answer is:
Upcasting
For more on the overall concept, which is Inclusion Polymorphism, I studied the following article: http://www.msdotnet.co.in/2014/05/how-to-implement-polymorphism-concepts.html
Related
Hello denizens of stack overflow, I'm having an issue (perhaps with understanding?) regarding polymorphism and generics. I want to be able to define a "system" that contains a "component". I also want to be able to extend systems and components to be able to have greater functionality.
I currently have two base classes, Component, and I/A_ComponentSystem (For the sake of brevity, I'm not going to be showing any actual code, just definitions):
public abstract class Component { }
public interface IComponentSystem { }
public interface IComponentSystem<TComponent> : IComponentSystem
where TComponent : Component { }
// The following are what should should actually be inherited from
public abstract class AComponentSystem : IComponentSystem { }
public abstract class AComponentSystem<TComponent> : AComponentSystem
where TComponent : Component { }
Below is an example component/system created:
public abstract class ITag : Component { } // This is to allow generating the code in a different binary. Hard to explain in the question, I'll clarify if need be
public class Tag : ITag { }
public abstract class ITagSystem : AComponentSystem<ITag> { }
public class TagSystem : ITagSystem { }
Below are some excerpts of actually trying to use the code/morph between the different objects (please note that the code isn't meant to be used in this way, but I'm writing unit tests to ensure compatibility between layers)
// This is the main system that will be passed around
TagSystem tagSys = new TagSystem();
// This is OK
ITagSystem ITagSys = (ITagSystem)ITagSys;
// This is OK
AComponentSystem A_TagSys = (AComponentSystem)tagSys;
// This is OK
AComponentSystem<ITag> ATag_TagSys = (AComponentSystem<ITag>)tagSys;
// This is OK
IComponentSystem I_TagSys = (IComponentSystem)tagSys;
// This is OK
IComponentSystem<ITag> ITag_TagSys = (IComponentSystem<ITag>)tagSys;
// Even the following is OK (which is why I am confused)
IComponentSystem<Tag> new_ITag_TagSys = (IComponentSystem<Tag>)tagSys;
//***This is where it blows up*** (1)
AComponentSystem<Tag> new_ATag_TagSys = (AComponentSystem<Tag>)tagSys;
I have another interface/class, SystemManager, which is defined thusly:
public interface ISystemManager
{
TComponent AddNewComponentToEntity<TComponent, TComponentSystem>(Entity e) // Please don't ask about Entity, it shouldn't be required for this snippet and I already feel like I've posted a lot)
where TComponent : Component, new() // Required for some reason or I get an error
where TComponentSystem : IComponentSystem<TComponent>;
}
Now, the specific block of code that I have here will throw an error as well:
//*** blows up here as well ***(2)
ISystemManager sysMan = new SystemManager(); // defined elsewhere
sysMan.AddNewComponentToEntity<Tag, ITagSystem>(entity);
As far as the errors that I receive, error (1) is:
Cannot convert type 'TagSystem' to 'AComponentSystem<Tag>'
Error (2) is below:
The type 'ITagSystem' cannot be used as type parameter 'TComponentSystem' in the generic type or method 'ISystemManager.AddNewComponentToEntity<TComponent,TComponentSystem>(Entity)'. There is no implicit reference conversion from 'ITagSystem' to 'IComponentSystem<Tag>'.
Now, as far as my question goes, it is thusly:
Why can I not convert TagSystem to AComponentSystem<Tag>? This seems like a valid morph.
Why is ITagSystem not converting to IComponentSystem<Tag>? It appears that Tag should still conform to ITag, which is supported.
Is there any way I could change my hierarchy while preserving my need for that many layers of abstraction?
Thank you to anyone for reading this and assisting me.
Note: Yes, this is for an EntityFramework driven game engine. I'm building it mainly as an exercise for myself, and so I can quickly spin up 3d projects for myself. Yes, I've built a few game projects before, no I'm not interested in "finishing" a game, I'm just tinkering and having fun.
Without a simpler and yet more-complete code example, it's impossible to provide specific advice in your specific scenario. However, the basic problem is that the types are indeed not convertible, just as the compiler says.
Why can I not convert TagSystem to AComponentSystem<Tag>? This seems like a valid morph.
TagSystem doesn't inherit AComponentSystem<Tag>. It inherits AComponentSystem<ITag>. These two types are not actually the same. Just because Tag inherits/implements ITag, that does not mean that AComponentSystem<Tag> automatically inherits/implements AComponentSystem<ITag>. If it did, then that would mean that a method or property of AComponentSystem<Tag> that normally would return a value of type Tag, could wind up being used in a situation where a Tag value is expected, but some other implementation of ITag is actually returned. This is because you would be able to cast to AComponentSystem<Tag>, and then use that reference to return the non-Tag implementation of ITag, to some code that only wanted Tag.
This is bad for what I hope are obvious reasons, so the compiler doesn't allow you to do that.
Why is ITagSystem not converting to IComponentSystem<Tag>? It appears that Tag should still conform to ITag, which is supported.
Without a good Minimal, Complete, and Verifiable code example, it's difficult to answer this part of your question, as the types you've shown don't appear consistent with the code you've shown. ITagSystem is declared as inheriting AComponentSystem<ITag>, which in turn implements only IComponentSystem, not IComponentSystem<TComponent>.
So based on the code shown, there's no reason even naively to think that the conversion could work. But let's assume for a moment there's a typo in the type declarations you've shown. Then the answer is basically the same as above: implementing IComponentSystem<ITag> is not the same as implementing IComponentSystem<Tag>.
Is there any way I could change my hierarchy while preserving my need for that many layers of abstraction?
Possibly. It depends on what these types actually do. Since C# 4, we've been able to specify generic type parameters on interfaces with covariance and contravariance. With a type parameter thus restricted, and interface members to match, the interface then can support specific casting scenarios like you're trying to do.
But note that this only works when the interface members really are compatible with such conversions. The compiler still won't let you do anything unsafe.
There are a lot of questions on Stack Overflow already discussing this. Technically your question could even be considered a duplicate of those. I hope the above addresses your immediate concerns, and gives you enough information to do more research and see if generic interface variance will work in your situation. If you need more help, I recommend you post a new question and make sure to include a good MCVE that clearly illustrates your question in the simplest way possible.
TagSystem distantly inherits AComponentSystem<ITag>, but you are trying to convert it to AComponentSystem<Tag>. (Note the lack of an "I" in the generic type.) Those two generic types of AComponentSystem<> are completely different, and you cannot freely cast between the two.
Same as point 1, just because Tag is a child of ITag doesn't mean that IComponentSystem<Tag> is a child of IComponentSystem<ITag>.
The answer is almost certainly yes, though exactly how depends entirely on how you are going to use it. You might also want to ask yourself if you really need this many layers of abstraction.
To give a better example of my first point, take for example a common generic type: the List. If generics followed the same inheritance rules as normal classes, then List<Car> would be a subtype of List<Vehicle>. But the difference between the two is that the first list can only hold cars, while the second list can hold any vehicle. So if these lists were parent and child, you would be able to do the following:
List<Car> cars = new List<Car>();
List<Vehicle> vehicles = (List<Vehicle>)cars;
vehicles.Add(new Truck());
You see the problem? The general rules of inheritance just allowed us to add a non-Car object to out list of cars. Or they would, provided that is a legal cast, which it isn't. In reality, List<Car> and List<Vehicle> are not related in any way, but are actually completely separate classes with no direct relation whatsoever.
Here is my program:
class Program
{
//DESIGN 1
abstract class AFoo
{
public string Bar { get; set; }
public abstract string SayHi();
}
class LoudFoo : AFoo
{
public override string SayHi()
{
return this.Bar.ToUpper();
}
}
class QuietFoo : AFoo
{
public override string SayHi() { return this.Bar.ToLower(); }
}
//DESIGN 2
class Foo{
public string Bar { get; set; }
public Func<Foo, string> SayHi { get; set; }
}
static void Main(string[] args)
{
//USING DESIGN 1
var quietFoo2 = new QuietFoo{ Bar = "Mariane"};
var loudFoo2 = new LoudFoo{ Bar = "Ginger"};
Console.WriteLine(quietFoo2.SayHi());
Console.WriteLine(loudFoo2.SayHi());
//USING DESIGN 2
var quietFoo = new Foo
{
Bar = "Felix",
SayHi = (f) => { return f.Bar.ToLower(); }
};
var loudFoo = new Foo
{
Bar = "Oscar",
SayHi = (f) => { return f.Bar.ToUpper(); }
};
Console.WriteLine(quietFoo.SayHi(quietFoo));
Console.WriteLine(loudFoo.SayHi(loudFoo));
}
}
I can accomplish the "same thing"-- actually not exactly the same thing, but similar things going two different routes.
Design 1) I can create an abstract class which forces the implementor of that class how to SayHi()
--or--
Design 2) I could create a class defines a SayHi property which is a function. (I'm calling it a delegate-- but I'm not sure that's the correct term for it here)
Design 1 bothers me because it could lead to a profliferation of classes
yet....
Design 2 bothers me because it feels redundant when I have to have Foo actually SayHi().
felix.SayHi(felix)
My question is whether it is better to use Design 1 or Design 2-- or perhaps neither of them. When I say better I am saying which is more practical in terms of being able to maintain my program. I ran into this when I created different classes which are going to be used to download files from different cloud API's (Google Drive, Box.com, DropBox)-- at first I created separate classes, but then I went the other route.
When it comes to these types of design choices, I find it helps to think about the objects in terms of the problem domain you're trying to model. You've shown LoudFoo and QuietFoo as differing in a single behavior, but this is a deliberately simplified example. In a real system, you may have compelling reasons to consider two objects as being conceptually distinct.
In the former version, SayHi is an instrinsic part of the class behavior, which is appropriate if the nature of that behavior interacts with its internal state in some way. Perhaps the implementation of SayHi depends on properties of the object that are specific to that derived class type.
In the latter version, SayingHi is a more like a tool that can be handed out to various instances. This is appropriate when there are no other reasons to distinguish between different types of Foo instances.
Stream is a good example of the former pattern, where the various methods it provides are intrinsic to the nature of the streaming operation. The various derived classes will make use of different states to implement their methods.
Comparer is a good example of the latter pattern, where lots of different object types want to operate using a notion of comparison. The classes that use this functionality don't need to have anything else in common other than wanting to consume this particular type of behavior.
Regarding your concrete application that prompted this question, what about the multi-class approach felt awkward? If there was redundancy creeping in, it likely indicates that the responsibilities could be factored in a different way that better modeled the problem. It's hard to say more without knowing additional details about the specific problem, but likely a good approach would be a combination of the two you proposed, with some single class responsible for the sequencing of the operation and a separate heirarchy (or set of interface implementations) implementing operations specific to each service. Essentially the interface (or base class) groups all of the various delegates you would pass in separately. This is akin to how a StreamReader takes a Stream and augments it with additional behaviors that operate on the Stream.
In Design 1 your behavior is implemented inside the class, but in Design 2 you're asking your caller to define the behavior.
I'm leaning towards Design 1 because it keeps the behavior implementation black-boxed inside the class. Design 2 could have your implementation changed whenever somebody instantiates a new object. I also don't like how the implementation is the responsibility of the caller.
If how you implement SayHi changes you only have one place to change it in Design 1, but you could potentially have several places all over your code to change it if you used Design 2.
As a rule of thumb: less code == more maintainable.
In the specific case you have, you are also having a decoupled design - the logic of how to SayHi is separate from the class that says it, giving you the option to compose the behavior. Low coupling is also a hallmark of code that is generally to maintain.
My preference would be with the second design.
The first design is more standard, and the logic is consistent (means that any other class using the LoudFoo (or QuietFoo) will have same result everywhere. However, it is reuseable, but only in its inherited path. Means that child class from LoudFoo (say DerivedLoudFoo cannot use SayHi logic defined in QuietFoo).
That may sound simple, but can be troublesome later on. You can read my answer at here
for real-life case.
The second is more extendable, but the drawbacks are it can have different behavior. Don't use this for core business process (such as insert/update/delete), as it will hard to debug or modify. However, this is best to use in Framework level for some methods such as OnAfterInsert, OnAfterSubmit.
Assuming this is more than a totally made-up example and could actually be translated into real code (which I have a hard time figuring out what it could be), I find option 2 terrible.
You can pretty much assign anything to SayHi, including a lambda that is not related to a Bar in any way, which doesn't seem to be your original intent.
You're basically trying to stick a nicely crafted functional peg into a good old object-oriented hole. Using a lambda you separated data (Bar) from behavior that operates on it, which is valid functional practice, but then by making Foo.SayHi a property, you're back to an OO style trying to encapsulate the two of them back into the same class. Seems a bit contrived.
Design 2 bothers me because it feels redundant when I have to have Foo actually SayHi().
If Foo class is redefined to
class Foo
public property Bar as string
public property SayHi as func(of string)
end class
Then closure can be used to create and invoke SayHi function without passing Foo as a function parameter:
dim Bar = "Felix"
dim Felix as new Foo with {
.Bar = Bar,
.SayHi = function() Bar.toLower
}
dim FelixSays = Felix.SayHi()
I'm leaning towards Design 1 because it keeps the behavior implementation black-boxed inside the class.
Design 2 is always ready to black-box behavior implementation, for example inside a factory method:
function CreateQuietFoo(Bar as string) as Foo
return new Foo with {
.Bar = Bar,
.SayHi = function() Bar.toLower
}
end function
dim Felix = CreateQuietFoo("Felix")
dim Oscar = CreateQuietFoo("Oscar")
This way the caller doesn't have to provide SayHi method to create a quiet Foo instance, he simply uses CreateQuietFoo factory method.
My question is whether it is better to use Design 1 or Design 2-- or perhaps neither of them.
Use Design 2 if you prefer Composition over Inheritance. It makes code more flexible.
i've been doing some research on interfaces and a simple layman's explanation for what it truly is. when searching through seas of books For some reason people love using overly complex explanations and jargon to explain truly simple concepts (guess it makes them feel big) and i have a gut feeling it's the same in this case.
so from what i could grasp, it seems like interfaces are nothing more than a way to reserve method names, their return type if any, and the type and amount of arguments they accept. so when a class implements an interface (or interfaces) it is forced to define the body of each method from the interface(s). Am i on the nose with this one or do i need to keep digging?
p.s. i know javascript doesn't have support for interfaces, but i still need to understand the concept because there are quite a few places where it's shown how to emulate to an extent.
For some reason people love using overly complex explanations and jargon to explain truly simple concepts (guess it makes them feel big)
Consider eschewing the editorial comments that impute bad motives to people who are trying to help you. That's a really bad way to try to get people to help you.
It seems like interfaces are nothing more than a way to reserve method names, their return type if any, and the type and number of arguments they require. So when a class implements an interface (or interfaces) it is forced to define the body of each method from the interface(s). Am i on the nose with this one or do i need to keep digging?
You are on the right track but you err in the details. In C#, for example, an implementing class is not required to provide a body. The method which corresponds to the interface method could, for example, be an abstract method in an abstract class, which would then not have a body. And in C# an interface can require members other than methods; properties, events and indexers, for example.
A more concise and typical way to express the idea that interfaces impose a requirement that a type supply members that match certain signatures is to say that the interface represents a contract that must be fulfilled by its implementer. But that might be too complex and jargonish for your gut to stomach.
I explain the concept to lay people using an analogy that most people understand - plastic molding.
The interface defines the shape of an object in the exact same way a mold will provide the shape of the finished product.
You could inject a mold with White plastic, blue plastic, something exotic like an Epoxy or clay.
What matters is, no matter what they are actually made of, they all have the same exact consistent shape to the purchaser of the product.
For code, this means no matter what code is used to implement the interface, they all follow the same consistent contract/shape to the end user.
I hope that might help a little.
Edit -
To extend the analogy to Abstract classes, imagine the next step in the molding process. You run a White, blue, and red plastic production run, but then each item needs to be painted at a separate factory, we just ship them out.
The item is not finished, but it does have its shape defined. Someone later will come and fill out the details that our factory left blank.
These items cannot be sold until they get that last painting step.
In code, the abstract implementation of the interface provides some (or none) of the implementation, but leaves another descendant class to complete the contract, and in the same way no one can create an instance of the class until the contract has been completed.
In the same way though, you can still refer to an abstract class in code, just like you can refer to the unpainted mold item as a "White molded thing" wither or not it is painted!
Edit 2
Here's a short example
void Main()
{
//IMold mold = new IMold(); // error - can't create instance of an interface
//Fruit fruit = new Fruit(); // error - can't create instance of an abstract class
Apple apple1 = new Apple(); // good
Orange orange1 = new Orange(); // good
Fruit apple2 = (Fruit)apple1; // good - Apples are fruit
Fruit orange2 = (Fruit)orange1; // good - oranges are fruit
IFruitMold apple3 = (IFruitMold)apple2; // good - Apples fit the Mold
IFruitMold orange3 = (IFruitMold)orange2; // good - Oranges also fit the mold
//now I can do this:
//Notice that `fruits` is of type IList<T> but the new is List<T>
//This is the exact concept we are talking about
//IList<T> is some kind of set of items that can be added or subtracted from
//but we don't have to care about the implementation details of *HOW* this is done
IList<IFruitMold> fruits = new List<IFruitMold>();
fruits.add(apple3);
fruits.add(orange3);
foreach( var fruit in fruits )
{
fruit.PlasticColor.Dump(); // ok I can read
fruit.PlasticColor = ""; // error - no Set defined in the interface
// depending on the **implementation details** of what type of fruit this is true or false
// we don't care in the slightest, we just care that we have some IFruitMold instances
fruit.RequiresPainting.Dump();
}
}
interface IFruitMold
{
string PlasticColor { get; }
bool RequiresPainting { get; }
}
abstract class Fruit : IFruitMold
{
private string m_PlasticColor = string.Empty;
public string PlasticColor { get; private set; }
public abstract bool RequiresPainting { get; }
}
//notice that we only define the abstract portion of the base class
//it defined PlasticColor for us already!
//the keyword `override` is required - it is to make it clear that
//this member is overriding a member from it's parent.
class Apple : Fruit
{
public override bool RequiresPainting { get { return true; } }
}
class Orange : Fruit
{
public override bool RequiresPainting { get { return false; } }
}
Yes, in a nutshell interfaces are there to declare and promise everyone else that a class will have certain methods.
This is good when you create generalized methods and function, where you want a more abstract design. All you want to know is that your function can receive an object that had methods A B and C.
Interface is just a simple empty class, that show the contract on how you real class should look. I think you have the concept ok.
They don't reserve anything (I don't understand what you mean by that), is just a way so when you build your class around the interface, you have a prior knowledge of how will your class look like. And also you can know before which methods will it have.
when a class implements an interface (or interfaces) it is forced to define the body of each method from the interface(s).
Yes. Interfaces are contracts. They let others know that your class implements certain functionality.
I would say its more than reserving the method name it is a way of making a contract that the method will exist and the caller will not need to know what it does but it will still be available to be called
A good example would be a pen and pencil both can implement an Iwriter interface with a write method but whoever calls the write method doesn't need to know that one uses ink and one uses lead the caller will just know that it is going to write words on the paper.
Interfaces provide a uniform way of interaction with a set of objects.
No matter what the object is, if it implements the interface we know that it will respond to a method defined in the interface. In this way, we can create objects that represent different things in a project and still interact with them in the same way. The actual implementation of the methods defined in the interface can be completely different, but they will take the same inputs and provide the same type of output.
Basically an interface is a contract which can define properties (getters and setters) or methods (with whatever parameters you require). If an object 'implements' the interface it needs to define a concrete implementation for ALL the properties and methods defined in the interface.
For unit testing or Inversion of Control containers interfaces really come into there own as you can call methods/properties on the interface without knowing anything about the object which actually implements it.
Interface is used to provide common functionality among a set of completely unrelated objects.
Lets say we have a bunch of animal objects and we need to separate pets from that bunch. The task of separation becomes really simple if we enforce a contract such that all the animals which are pets needs to implement IPet interface.
Summary
Let's say I have two C# 4.0 classes, one inheriting from the other:
class ParentKey {}
class ChildKey : ParentKey {}
I want the compiler to issue an error if I try this:
ChildKey c = new ChildKey();
ParentKey p = c; // I want compiler error here!
Essentially, I want to use inheritance for reusability purposes, but I want to avoid polymorphic behavior (or more specifically, assign compatibility) that normally comes with it. Similar to C++ private inheritance.
Example
Specifically, I'd like to avoid accidentally mixing ParentKey and ChildKey when used as keys of some container (since their implementations of GetHashCode() or Equals() might be incompatible). For example:
Dictionary<ParentKey, object> d = new Dictionary<ParentKey, object>();
d.Add(new ChildKey(), new object()); // I want compiler error here!
What I Tried
Now, I know I can use composition to avoid the inheritance altogether, but I'd like to avoid the verbosity that comes with this solution (my ParentKey can be quite complex, and there may be many levels of inheritance hierarchy).
Another solution is to always use tailor-made IEqualityComparer, or to explicitly create new ParentKey based on the ChildKey prior passing to the container, but both of these are easy to forget, and may be comparatively hard to diagnose at run-time.
Attempting to make the conversion explicit...
class ChildKey : ParentKey {
public static explicit operator ParentKey(ChildKey c) {
// ...
}
}
...yielded compiler error CS0553: user-defined conversions to or from a base class are not allowed.
Struct inheritance would be ideal here (so the "end" portion of ChildKey is "cut-off" when passed to something that is declared as ParentKey), but this is not supported in C# either.
Am I missing something obvious here? Any ideas? Thanks.
You're working directly against the by-design purpose of the type system, which is to make it always possible to assign a more-derived type to a variable of a less-derived type. (Moreoever: suppose you did somehow manage to prevent implicit reference conversions from Derived to Base -- what stops you from converting Derived to object and then explicitly converting object to Base? It seems perverse to prohibit something at compile time that we cannot prevent at runtime.)
I agree that from a language design perspective, it is possible to create a language which avoids conflating code reuse via inheritance with subtype polymorphism. However, we chose to conflate those two things a long, long time ago. You're going to have to either live with that choice, or use a different language that gives you the feature you want. (*)
My advice: stop spitting into the wind. Either use composition, or carefully craft your Equals and GetHashCode methods so that everyone plays together nicely.
(All that said, I have often shared your frustration that reuse via composition has so much verbose "ceremony" around it. It would be great if we could find a way to lower the syntactic burden of composition.)
(*) I am definitely not an expert on Eiffel; that said, your idea seems to me to be like the Eiffel concept of non-conforming inheritance. Perhaps an expert on Eiffel would like to comment on this?
How about:
class BaseKey
{
// all functionality here
}
class ParentKey : BaseKey
{}
class ChildKey : BaseKey
{}
?
public struct Exclusive<T>
{
public Exclusive(T item)
{
if (c.GetType () != typeof(ParentKey))
throw new Exception (); // I want compiler error here!
Item = item;
}
public T Item{get; private set;}
// todo: add implicit cast to T
// todo: add forcing non-null to get_Item
}
This is a shortcoming of the C# (and C++) language, I hope it will be fixed (but doubt it ..)
In my (not common) opinion polymorphism is an anti pattern, basically a bad idea that somehow became popular, this becomes more and more obvious the more functional code you write.
On the other hand, extension is an invaluable coding mechanism and trying to replicate it with composition just so you can avoid polymorphism is tedious and bug prone and doesn't scale.
(as a side note, IMO it would not be hard to add this to the language, ie an "extends" keyword Class ChildKey extends ParentKey {} etc)
What I do is use the "curiously recurring template pattern"
abstract class KeyBase<TDerived> { /* common functionality here */ }
class Key : KeyBase<Key> { /* inherit common functionality */ }
Of course this does not stop a user from doing
Key c = new Key();
KeyBase<Key> p = c;
But it has a few advantages:
It becomes more explicit from from the template argument that the intention is extension and that no KeyBase<Key> variables should be declared.
KeyBase methods can now accept and return TDerived, this is especially useful when dealing with immutable classes
You can easily create different Key types (KeyEx) which have identical API but are different types (typeof(Key)!=typeof(KeyEx)).
I started naming my class instant variables like this:
Car car;
The reason being that I think a car is a perfect description for a variable and I don't need to add additional information.
This worked great for me and I was very happy, but there is one issue that drives me crazy. It messes with the IntelliSense if I want to do the type it may go for the private variable and vice versa.
I've seen people do:
Car myCar;
I'm not crazy about it, but it probably would work.
Any ideas about how to do this better?
I would like to add that this mainly applies to instances of classes created inside of methods.
There are two things I would point out when seeing such code.
You obviously don't have a naming convention for variables. I think such a convention is very useful, especially for distinguishing Properties, member-variables and local variables.
Common Conventions in the .NET ecosystem are:
_privateVariable (Used by Microsoft
and a lot of designer generated code,
e.g. linq2sql)
m_privateVariable (Also used by Microsoft, I think TypedDatasets are
generated using this convention, but I'm not sure.)
Properties always use PascalCaseAndNoExtras
loacl varaibles are always camelcaseAndNoExtras
The second thing is about naming a variable like the class at all. I think it is better not to use the name of the class as a variable name. A good variable name should convey the type and the meaning of a variable in the scope the variable is present.
E.g. if you wanted to display information about a car a customer likes to rent you would rather name your variable m_CarToRent instead of m_Car.
You also can use this keyword this.car. It will solve your intellisense issue.
I myself prefer what Daniel suggested to use underscore like _car.
Some people, like me, use _Car for private member variables.
One of the good practices would be:
public class Driver
{
private Car _car;
public Car Car { get { return _car; } }
public Driver(Car car)
{
_car = car;
}
}
_ would mean, the clients of the class don't see this one, and it's better then 'm_' because it does not add anything to just '_' or 'my', because "my" is already an assumption of the usage.
As a guidance, you can try installing Resharper http://www.jetbrains.com/resharper/ and you will soon get used to a good naming convention.
Before i tried it, i was always changing my naming convention styles, and could not get rid of the awkward 'this' keyword here and there.
I will typically use "current" in front of the (local) variable, especially if it's in a loop.
Car currentCar = new Car();
And
foreach( var currentCar in CarList ) {
currentCar.Xxxx();
}
I find this helps with readability, but it's completely subjective.
The first approach is to use prefixes. I use prefixes such as m, e, v, i, p (MemberVariable, Event, Volatile, Index/Iterator, Pointer), etc which allows me to see these different usages of variable grouped nicely in intellisense lists, as well as understand instantly how a variable should be used just from its name. I really don't understand why some people don't do this - it is a long proven approach to speed up coding and make programming easier and less error prone (especially with pointers and pointers to pointers). Over the years I've see a lot of avoidable bugs from programmers on my team who refused to follow these simple conventions.
The second is to differentiate type names and instances better.
Using Car car, or even worse, a property: Car Car {get;set;} as you rightly point out is rather confusing. It's long been accepted that differentiating names based only on case is a bad thing to do, and having two names that are identical (type, property) is even worse.
But there are approaches that can be applied to avoid this (especially for parameters/locals where you may not be using prefixes):
Use synonyms: Vehicle car;.
Use general (type) and context-specific (instance) terms Vehicle licensedVehicle. This helps your instance code describe not just that something is a car, but what form of car you expect it to be
Lastly, things can get worse as you augment your code in the future. Bear in mind what happens when you build a class hierarchy with vague (effectively "non-scalable") naming:
You start off with names like Vehicle.Type. This seems logical: The type of the vehicle (private, passenger, light-goods, heavy-goods). Then you add derived classes Car, Bus, Truck. For a Bus (Type=passenger) you want to add a "Type" (minibus, coach, double-decker). So now you have base class Vehicle.Type and derived class Bus.Type that mean completely different things. Avoiding use of the generic term "Type" in both cases by calling them (for example) Vehicle.VehicleType and Bus.BusType clarifies things immensely, and eliminates any chance of programmers mixing them up.
(This isn't a great example, as I've based it on the Car naming idea, but hopefully it gets across the general point - good, specific, descriptive naming minimises the confusion that users of your class and maintainers of your code will face in future)
Not only is that confusing to VS, but also it borders on being confusing conceptually. Car should be something like Accord, Celica, or Mini and the instance myCar, car1, etc. :-)