Re: Random array element gets value changed with variable
1) About the syntax.
I understand that it can be a bit confusing for someone with previous experience in C++, but the confusion has more to do with not fully understanding the type system of C#. Once you do, the syntax stops being a problem. In fact, I personally appreciate the consistency of using the same "." operator for both value and reference types. Note that it is called "member access operator", and the name describes precisely what it does in both cases. Furthermore, C++ is actually not so different. IM(H)O, the C++ "->" operator has less to do with making pointer variables distinct from other types of variables, and more to do with providing syntactic sugar for this:
(*pVar).member // equivalent to pVar->member
As you can see, that makes it obvious that it's a pointer, but it's a pain to type in, and it's not particularly visually appealing.
Now, with C# references, you can't directly assign a memory address, or use pointer arithmetics, or explicitly delete memory. In other words, you never directly work with their pointer-like aspects, but with the pointed-to object instead, so there's no need to explicitly dereference references - it's done automatically.
In C#, your responsibility is to know to what of the two major type-kinds you're working with, and it's not hard to find out (reflection enables IDEs to provide whatever info is relevant, and there's documentation available in addition).
2) About your inheritance question.
This is a good question, and it's language independent (as long as we talk about OO languages). This has to do with OO application design. First, the term "abstract class" denotes a class designed to be a base class to other types, while not providing a way for the client code to instantiate it. In other words, it's an abstract type, and variables of that type can only reference objects which are instances of classes derived from it.
If your class has those properties, than it's the correct term. Otherwise, you would just call it a base class.
Now, how do you get your objects to exhibit derived, specialized behaviors, via a base-class reference?
As you noticed, without type-casting, you can't just call derived-class specific methods.
But, type-casting only works if you know what the actual type of the object is, and often enough, you don't.
So, how to solve this?
I assume you experimented with Windows Forms? Let's examine the design briefly. The IDE creates a class to represent your main form, and usually names it Form1. Form1 is derived from Form (provided by the .NET library), from which it inherits some methods/properties and implementation. You then add your own, application-specific methods, run the code, and it all works. And yet, the framework that runs your windows application has absolutely no idea of your Form1 class, or your application-specific methods.
How and why, then, it works at all?
Because of how the base class, Form, is designed. The purpose of the base class, with respect to the calling code, is to provide a well defined interface (public methods/properties) for the calling code to rely on.
So, the framework only sees this abstract interface, and calls its members, which in turn, end up, one way or the other, calling your application-specific methods.
For this to work, a bit of planing is required, and experience helps a lot.
Essentially, the idea is to override inherited abstract or virtual methods in a derived class, so es to make them do something else, or something in addition, or call methods on other objects, etc. Alternatively, the base class can provide ways to "configure" it with other objects.
For example, even if you don't override any methods in Form1, and only use event-handlers, when you assign an event handler, you're actually configuring the base class, Form, with a method to call when the framework raises the given event.
Another way is to pass an object to a method, which would then assign it to some internal variable some other method later uses. Setting a property essentially has the same effect.
In your case, you have to think about what all of the types are required to do, and what the calling code is required to do, and how to abstract it all away in a unified interface.
For example, you wouldn't create a bunch of different methods like Potions.Drink(), Scrolls.Use(), Gold.Spend(), Rings.Wear(), etc., but would find a name that describes all of those on a higher level, and put it into the Item class.
A good candidate is, for example, Item.Use().
Then, the calling code would just call the Use() method, and the actual derived class would implement it in a way that is suitable for the kind of item it represents.
So, you must make sure that your abstract interface is general and expressive enough - and to do that, you must carefully study what the requirements are, what the calling code is supposed to do, what your game should be able to do, etc. Don't hesitate to take pen & paper - they can be great tools.
If you provide more detail, we can provide a more focused guidance.
In the meantime, you might want to check out Design Patterns, as these are well-established, time tested solutions to common design problems.
Also, this is my post from another thread that among other things, has some (I think) illustrative examples that show inheritance in action (VS solutions attached), so if you take some time to examine it, it can get you started. The first example is rather simple, to illustrate the concept, and the other is an implementation of the Command design pattern.
Re: Random array element gets value changed with variable
Wow, that's exhaustive :) I'm familiar with overriding methods and how Windows Forms work, especially in VB.Net (thank you, two years of college). It couldn't hurt to know more about design patterns, but I think my question still remains one of C# language specifics.
Here is an example that succinctly illustrates the issue.
Code:
Item tmpGoldSm = new Gold(Content.Load<Texture2D>("gold small"), r.Next(2, 50));
This line comes from my Load method. It creates a Gold object with the base class Item. The random number is the amount , a property that no other item really need have.
Code:
iMasterList = new List<Item>() { tmpFood, tmpFood, tmpGoldSm, tmpGoldSm, tmpPotion1, tmpPotion2, tmpScroll, tmpScroll2, tmpRing, tmpRing2 };
When this line runs, the temporary gold variable goes into the master list of items. At this point, it still has its derived class info.
Later, in having to do this:
Code:
for (int it = 0; it < maxMapItems; it++)
{
int tmpR = r.Next(0, iMasterList.Count);
//put randomly-selected item into this map's items, and give it a random starting
position on the map
Item tmpItem=
new Item(iMasterList[tmpR],
new Vector2((float)r.Next(4, maxTilesH - 4),
(float)r.Next(4, maxTilesV - 4)));
mapItems.Add(tmpItem);
... I lose the Gold object information that was contained in iMasterList[tmpR]. So later, I can't verify that the object is gold to add the amount to the player's gold. If I could just copy the object in its entirety to the new list, I think this could be avoided, but currently that doesn't seem possible, because
Code:
Item tmpItem = new Item();
tmpItem = iMasterList[tmpR];
just made tmpItem a pointer.
Alternatively, I've thought of giving Item its own amount and only overriding it in the Gold class--is that the right idea from a design perspective? Checking for such properties in every object of a derived type would add a lot of needless arithmetic operations, though (i.e., player.Gold + 0 for every item that doesn't have an amount).
Re: Random array element gets value changed with variable
This is unnecessary:
Code:
Item tmpItem = new Item();
tmpItem = iMasterList[tmpR];
You create a new object and immediately throw it away. Simply use
Code:
Item tmpItem = iMasterList[tmpR];
Re: Random array element gets value changed with variable
Hi Ed,
In my original post, you can see that that particular assignment was causing the first problem. I'm afraid all that does is make tmpItem a reference to the same object as iMasterList[tmpR], which in turn, causes changes to tmpItem.startingPos to affect the original item.
Re: Random array element gets value changed with variable
I was thinking about this a lot last night, and I realize now what I should do (I think).
I'm going to implement new, intermediary sub-classes in Item. A class like Usables : Item would comprise potions, scrolls, and anything else with a Use method. I already have an Equipment subclass for all the various equippables. The Gold class will be on the same level as these, and used just for gold, since its only unique method will be Pay.
Making Lists of each of these types will let me aviod copying my gold, potions, etc. to a generic Item object, and losing the derived class info. I'll just have to add a few more loops to the CreateItems() method.
Thanks for making me think of design, Cthulu :)