C# Workshop - Week 6 (Ch. 18 - 19)

Started by
5 comments, last by Emmanuel Deloget 16 years, 8 months ago

Welcome to the GDNet C# Workshop – Ch. 18 - 19

For a complete introduction to this workshop, please look here. Workshop Overview This workshop is designed to aid people in their journey to learn beginning C# (C-Sharp). This workshop is targeted at highly motivated individuals who are interested in learning C# or who have attempted to learn C# in the past, but found that without sufficient support and mentoring they were unable to connect all the pieces of this highly complex but powerful programming language. This is a 'guided' self-teaching C# workshop. Each student is responsible for taking the time to read the material and learn the information. Additionally, this workshop does not attempt to defend C# as a language, nor does it attempt to demonstrate that C# is either more or less useful then other programming languages for any particular purpose. People who intend to start a discussion about the differences between C# and ANY other languages (except as are relevant to a particular discussion), are encouraged to do so elsewhere. This workshop is for educational, not philosophical discussions. Finally, the community and tutors that arise out of this workshop are here for making the learning process run more smoothly, but are not obligated to baby-sit a person's progress. Because everyone will be working from the same references (.NET Book Zero and optionally the C# Language Specification 1.2 & 2.0), students may find it easier to get answers to the specific questions they might have. There is no minimum age requirement, and there is no previous programming experience required. However, we will be moving quickly so it's essential that students stay on task and dont fall behind. Experienced C# Programmers Feel free to post your own additional knowledge about the topics, however please try and keep the information you provide objective. If you MUST provide subjective/opinion-based information, please do so by marking the paragraph with [opinion] tags. This will make it clear to the readers what is fact, and what is opinion. Also, it may be relevant to mark some information with [observation] tags for information which you’ve “observed” but may not be fact. Finally, if you’re providing information which is related to common programming errors, you might tag it with a [warning] tag. Also, feel free to post links to additional resources about the topics for this week. I will do my best to add those to the “Additional Resources” section at the bottom of this post. Quizzes & Exercises Each week I will post 'quiz' questions and exercises in the weekly thread. Please try and answer them by yourself. Once you've done so, feel free to look over the answers provided by others and submit your own answers if you've not yet seen them posted. Discussion about the quiz questions and answers is encouraged for clarification. Finally, experienced C# programmers may feel free to post quiz-like questions and exercises of their own.

Chapters 18 - 19

Introduction Welcome to week 6 of the C# Workshop. This week we'll take a look at the real meat of Object Oriented Programming - Inheritance and Virtuality (aka polymorphism). Inheritance, by and large, is a mechanism which allows a developer to easily reuse portions of code, without having to re-write entire class libraries. It is possible to take something which you, or someone else, has already written and modify only the portions necessary in order to gain the functionality you need. It's not uncommon for [bad] programmers to copy and paste a class or other construct which has functionality they need and then make modification to it as necessary. However, this creates duplicate code and requires that developers maintain possible bugs in both instances of code. Inheritance allows you to get the effect of copying and pasting without actually doing it, and thus doesn't create duplicate code that must now be maintained. When working with Inheritance, it's common for programmers to think in terms of what we call an IS-A relationship. That is, in order for inheritance to make the most sense, it's important to think about whether or not the derived class we're creating IS-A more specific type of the base class. For example, IS-A Car a type of Vehicle? IS-A Mage a type of CharacterClass? IS-A Weapon a type of item. Whenever you can answer "yes" to the IS-A question, it's a good indication you may have the possibility of inheritance. On other hand, it's important to remember that just because something IS-A type of something else, doesn’t mean inheritance is required. Often times creating an instance of a class and giving it a field called "Type" or something similar is enough. Inheritance is only encouraged when the specific type being created has significant enough differences from the base class that deriving a new type is warranted. Finally, with the introduction of Inheritance we also gain something referred to in our text and Virtuality, but is often referred to as Polymorphism in other texts. When a class inherits a base class it gains all the fields, methods, and properties of the base class. As result, the new derived class can be treated by the programmer and the compiler as though it IS-A instance of the base class. Why not, after all? It does have everything the base class has. Now, although the new class can be treated as though it is an instance of the base class, the programmers who implemented the base class might have wanted to allow those who implement a derived class to be able to override the functionality that was specified in the base class. To do this, the base class uses the keyword "virtual" and the derived class uses the keyword "override." Once this is done, an instance of the derived class can be treated as an instance of the base class, while still maintaining the functionality which makes it unique. This will make more sense once you've read the text and looked at some examples. Well, that concludes the introduction to week 6. Feel free to ask questions here in the week 6 forum after you've read over the text. And dont forget to answer the review questions. They are there to test your knowledge of the reading, and to determine whether you picked up on the most important aspects of the text. Additional Resources None...

Good Luck!

[Edited by - JWalsh on August 9, 2007 11:37:17 AM]
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Advertisement
Quote:
For example, IS-A Car a type of Vehicle? IS-A Mage a type of CharacterClass? IS-A Weapon a type of item. Whenever you can answer "yes" to the IS-A question, it's a good indication you may have the possibility of inheritance. On other hand, it's important to remember that just because something IS-A type of something else, doesn’t mean inheritance is required. Often times creating an instance of a class and giving it a field called "Type" or something similar is enough.


[Opinion][WARNING]

And in my experience, all of the above examples probably fall into the above caveat. The type of an object isn't readily/cleanly available at runtime, so placing information there ("this vehicle is a car", "this character is a Mage", "this item is a Weapon") is problematic. These are properties (hint, hint) of the vehicle/character/item.

Inheritance is best used when you don't care what the derived class is. For example, output classes. It is useful to have a common base class for output to a file and output to the screen so that your code can use either; not particularly caring where the data ends up. If your code cares what derived class a particular object is, this is a good indicator that your design is flawed, and inheritance might not be the way to go.

[/Opinion][/WARNING]
Quote:Original post by Telastyn
[Opinion][WARNING]
And in my experience, all of the above examples probably fall into the above caveat. The type of an object isn't readily/cleanly available at runtime, so placing information there ("this vehicle is a car", "this character is a Mage", "this item is a Weapon") is problematic.
Why is it problematic?

Much of the time, you never need to know what the actual type of an object is; you only need to know what you can do with it, which is where things like interfaces and inheritance trees are really at home. You don't care whether the object the player is trying to use is an IonCannon or a LaserTurret; all you care about is whether it can be Fired(). By keeping all of your code on a 'need to know' basis, you reduce the number of factors that can affect a section of code, and thus the chance of breaking it when changing something.

Also, some information about the runtime type of an object is readily available - specifically, testing whether an object is an instance of a particular type or of a type derived from that type is very simple using keywords like 'as':

void onPressFireButton(){  IFireable obj = getObjectThePlayerIsStandingNextTo() as IFireable;  if(obj != null)  {   obj.Fire();  }}

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

Quote:
Much of the time, you never need to know what the actual type of an object is; you only need to know what you can do with it, which is where things like interfaces and inheritance trees are really at home.


For you or I perhaps, but for people who are not terribly experienced with program design, following the simple "IS-A" guideline will create scenarios where they need to know what type the object is.

Quote:
You don't care whether the object the player is trying to use is an IonCannon or a LaserTurret; all you care about is whether it can be Fired(). By keeping all of your code on a 'need to know' basis, you reduce the number of factors that can affect a section of code, and thus the chance of breaking it when changing something.


Absolutely.

Quote:Original post by superpig
Why is it problematic?


Let's look at the example of Mage extends CharacterClass... There are a variety of things that need to know what type of CharacterClass is being used. The name of the CharacterClass, things that have "Mage" as a prerequisite, perhaps some presentation things...

Sure, you could supply a virtual Name property and various prerequisite fields, but at that point what are you gaining from inheritance? You're not really changing behavior, and certainly not in any way that couldn't be done (better) via the strategy pattern.

Quote:
*snip* is/as


But as you've already said (much better than I), much of the time you don't/shouldn't care what type of derived object an instance is. Is/as and reflection are there for the exceptions to 'much of the time'.

I was just trying to communicate the tendency for beginners to over-use inheritance to the detriment of that derived class apathy.



Quote:Let's look at the example of Mage extends CharacterClass... There are a variety of things that need to know what type of CharacterClass is being used. The name of the CharacterClass, things that have "Mage" as a prerequisite, perhaps some presentation things...


There are no things that need to know what type of character class being used is...At least none that I can think of. Perhaps you can give some examples?

If things need to know about the class, then the interface or base class isn't engineered correctly.

Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Indeed. But what is the reasoning behind subclassing them rather than simple instantiation? Especially since the subclasses will be instantiated once at most?

I can't think of any property that isn't better handled as a property or any method which wouldn't be better served as a drop-in strategy since they are reused (like the dnd money and hp calculations). The various independent Class properties are only loosely tied because the rules say so (for now), not some intrinsic requirement of design.


Ah, wait... oh. Delegates aren't covered for another 3 weeks... How unfortunate. Well, that's reason enough I suppose to eschew strategy style designs.
For those who want to know more about how to decide whether a class should be inherited from another one, you'll find some very interesting (and general) articles about object oriented design on objectmentor.com.

This topic is closed to new replies.

Advertisement