C# polymorphism with cloning - c#

Let me first try to explain what I'm trying to achieve.
I'm making a game where the player can pickup power-ups(which I called, for some reason, "Loot" in my game). So here's a really basic form of my Loot class:
public class Loot : Sprite
{
//Properties and fields...
public Loot(/*parameters...*/)
{
}
public virtual OnPickUp(Player player)
{
}
}
Player and Sprite are classes from me. Here's my problem: my sprite class holds a position(a Vector2, a struct from XNA representing a vector) and from my understanding of how C# works, copying two sprites will copy the reference of eachother, therefor, whenever I change one's position, it will change the other one's too.
Whenever a loot should spawn, I have a class holding the possible loots that can spawn which returns a random one and the loot is copied and shown to the screen, but as soon as I get more than one of the same type of loot, it messes up because of the reference copy problem (both will share the same position and only one will be visible).
So then I tried creating a new Loot object whenever I needed to spawn a new loot, so I had to provide a constructor with multiple parameters to easily copy a loot this way:
(Let's pretend toSpawn can be any type derived from the Loot class, like a HealthPack, or whatever)
Loot spawning = new Loot(toSpawn.Position, toSpawn.Color /*etc...*/);
It looked right until I decided to implement "OnPickUp". Since I create a new Loot object rather than the proper child class, the functionality of toSpawn's OnPickUp function would disappear and picking up a loot would end up doing nothing(it would only call the base class Loot's empty function).
Obviously, I am doing something wrong here. I don't have much programming experience, and even less with C#, so I really have no idea of how I can fix this. I tried using an Action< Player> object representing the OnPickUp functionality, it would work but still limit me quite a lot(since I have to pass a static function as an Action< Player>, therefor limiting me to use the information of the player parameter and preventing me from using the sub-class specific information).
So, finally, my question really is: What would be a better design to allow having sub-classes with overloaded functions, but still being able to clone the base class and its properties?
Thank you for your precious time.
If anything is not clear enough(and I know it's not), then just ask me in the comments and I'll try to describe my problem in more details.

have your Loot class implement ICloneable
public abstract class Loot : ICloneable
{
public virtual object Clone()
{
Type type = this.GetType();
Loot newLoot = (Loot) Activator.CreateInstance(type);
//do copying here
return newLoot;
}
}

I think I must be missing something with this question because Vector2 is a structure and not a class. Any direct assignment of one Vector2 to another automatically creates a copy.
var v2a = new Vector2(10.0f, 20.0f);
var v2b = v2a; //`v2b` is a new instance of `Vector2` distinct from `v2a`.
Your issue sounds like the PossibleLoots class isn't randomizing the position of each Loot instance created.
I assume your game logic says something like "each level there shall be a maximum of 10 loots spawned", so your PossibleLoots class creates all the possible Loot objects at start-up but doesn't display one unless it is asked to "spawn a loot".
So, if that's right, isn't this the kind of thing you need?
public class PossibleLoots
{
private IList<Loot> _loots = new List<Loot>();
public PossibleLoots(int maxLoots)
{
for (var i = 0; i < maxLoots; i++)
{
_loots.Add(new Loot(this.GetRandomPosition()));
}
}
private Vector2 GetRandomPosition()
{
// Your logic here to create suitable locations for loot to appear
}
// Rest of your `PossibleLoots` code
// to spawn each `Loot` and to deplete the `_loots`
// collection when the player picks up each `Loot`
}
Please let me know if I've missed the point of this question.

Vector2 is a struct not a class, so your original problem sounds like it is due to holding two references to the same Loot object, rather than having two different Loot objects with references to the same position.
The class responsible for creating Loot objects should be creating new instances of the relevant Loot subclass, rather than creating the base class. In your design, Loot should probably be an abstract class or even an interface, and you should use the abstract factory pattern to create the desired type of Loot object.
For example:
class LootFactory
{
const int numLootTypes = 3;
public Loot CreateLoot(Vector2 position)
{
Random rand = new Random();
int lootIndex = rand.Next(numLootTypes);
if (lootIndex == 0)
{
return new HealthPack(position);
}
if (lootIndex == 1)
{
...
}
...
}
}

To me it really sounds like you're still going about this the wrong way. While the answer given would work, it's not something you should have to do.
If you want to spawn a new loot and you want it to be a random of the possible types of loot, your constructor of the Loot class should do all that work. There shouldn't be any need for cloning or ICloneable.
When a new loot object is created, it should randomly become the type of loot it's going to be, no need to keep a list of all possible types somewhere and clone from them. The new loot object would then have it's own position and behaviors and work exactly like you're expecting it to.
Or am I just misunderstanding what you're trying to accomplish?

Related

Is it possible to change an object type in C#

I am having some problem in order to meet a client request.
I will try to keep the example very simple just give an idea of the problem and hopefully come up with a solution.
At this point we have a class "Shape" for example, and shape has some specializations, it can be square, triangle etc.
so far so good, everything working great.
Now for some reason my client wants to change a square that already exist in the system into a triangle but keep all the data from shape.
is that possible? any workarounds for that?
You can not change the runtime type of an object. Just create a new triangle, copy over all the relevant values and throw away the square. This may of course become tricky if the square is already referenced by a lot of other objects because you will have to update all references.
If replacing the object is not an option, you will probably have to come up with a generic shape class that can act as any kind of shape. This class could, for example, be a thin wrapper around an instance of one of the concrete shape classes. This enables you to just replace the wrapped square with a new triangle while the outside world can keep all the references to the wrapper class.
It is not possible in terms of replacing the type of an existing object without creating a new object of the desired type and manually updating all references to it (which is highly error-prone) - which I would consider a workaround.
Design-wise, the if the "type" (in the sense of behaviour, not of an actual type in the static type system) needs to be flexible, the problem can be solved with delegation. The object itself would remain the same, but a delegate is exchanged.
You can't change the type but you can solve this with a proper design.
If the idea is that each object is a Shape and it has additional information, which has to be replacable, it makes sense that it would be held as a separate member. For example (pseudo):
public class ShapeContainer
{
public int x { get; set; }
public int y { get; set; }
public ISpecificShape SpecificShape { get; set; }
}
public class Triangle : ISpecificShape
{
// ...
// ...
}
public class Rectange : ISpecificShape
{
// ...
// ...
}
This way, you can change the specific shape.
If you want it to be typed, you could add the following generic Get function to Shape:
GetSpecificShape<T>() where T : ISpecificShape
{
return (T)this.SpecificShape;
}
This will raise an exception if the data types do not match but that's consistent with your design requirements.
What do you think?
What you need is called inheritance.
Here is a model of that :
Create a StrokeStyle class
width
color
type (dashed, solid)
Create a FillStyle class
color
type (solid, gradient)
Create a VectorShape class that has strokeStyle and fillStyle properties (each being an instance of the classes).
Create Square and Triangle class, both being inheriting VectorShape class. They will share VectorShape properties. You will have to replace your square instance by a new Triangle instance and copy the properties you want to keep.
You can also do a single class with a shapetype property wich will be "square" or "triangle"... then you gain the benefit of changing the type without replacing the object. But you wil have to handle the shapetype in all methods ie : computeArea(). And this will lead to a huggly unmanagable code. This is possible but it's the bad way.
You can convert between data types. The results can be placed in a new object. The type of the original object does not change. But usually you only provide a mechanism for this when it makes sense to do so. In the case of converting a square into a triangle, I don't see how that would make sense but maybe there's something about your specific application where it would make sense (ie, convert a square to a triangle with the same size perimeter or area).
See Using Conversion Operators on MSDN for examples of converting between different types.
From Casting and Type Conversions on MSDN:
Because C# is statically-typed at compile time, after a variable is
declared, it cannot be declared again or used to store values of
another type unless that type is convertible to the variable's type.
For example, there is no conversion from an integer to any arbitrary
string. Therefore, after you declare i as an integer, you cannot
assign the string "Hello" to it, as is shown in the following code.
There is a Convert.ChangeType(dObject, typeof(SomeClass));
But for the conversion to succeed, value must implement the IConvertible interface, because the method simply wraps a call to an appropriate IConvertible method. The method requires that conversion of value to conversionType be supported.
Define and implement a virtual Clone() method in your Shape class. You have two "reasonable" options. Whichever implementation you choose you can't just "invent" the data that isn't there - the square has one side size and the triangle has 3.
First option is to manually copy all fields around:
class Shape{
public virtual Shape Clone(Shape target = null){
if (target == null) target = new Shape();
target.Prop1 = this.Prop1;
return target;
}
}
class Square{
public override Shape Clone(Shape target = null){
if (target == null) target = new Square();
base.Clone(target);
if (target.GetType() == typeof(Square)){
target.PropSquare1 = this.PropSquare1; // some casting etc
}
}
}
// change type:
var triangle = new Triangle();
square.Clone(triangle);
Second option, which I prefer trades in performance for convenience. It is to use a serializer to serialize the shape as one kind and deserialize as another. You may need to process the serialized result in-between. Below is a pseudo code version:
class Shape{
public virtual T Clone<T>() where T: Shape{
var data = JsonConvert.Serialize(this);
data = data.Replace("Square","Triangle");
return JsonConvert.Deserialize<T>(data);
}
}

Cannot reference public object in another class, please look at my source and let me know what I'm doing wrong

I'm learning C# and I'm currently playing with Monogame. What I'm trying to do is declare a public instance of the System.Random class called "randVar" in my Game1 class and then access it from my Testz (derived from Sprite) class. This is not working, it tells me "The name 'randVar' does not exist in the current context.' I'm scratching my head trying to figure out why, because randVar is public I thought I should be able to access it.
My sourcecode is https://gist.github.com/4225880.
To be able to access the randVar member of the Game1 class, you have to first have an instance of the class. It's the same as any other public member of a class. It currently doesn't exist within the scope of the Testz class. If you're just wanting a random number, you should just do Random randVar = new Random() inside your Testz class.
You cannot reference instance variables defined in one class from another without instantiating the first class in the second. You can do the following in your TestZ class:
Game1 oGame1 = new Game1();
Then you can do:
location.X = oGame1.randVar.Next(0,100) * .01f * screenBounds.Width;
You define randVar in in Game1 but use it TestZ. Just move the definition into TestZ or better yet Sprite.
Also, you should know that Random is not thread safe. So its better to have each class keep its instance.
You have to add the static modifier to your variable's declaration:
public static Random randVar = new Random();

Static vs. public C#

I know that it's been answered multiple times here on SO, but I still don't get the nuts of bolts of what exactly it means to instantiate a class. I read this and it did help my understanding.
I know that static classes like Console cannot be used with the new expression like Console c = new Console() because there aren't any instance variables in that class. I also know that static classes provide on 'generic' methods and are generally used for Math functions. I know that once you instantiate a class like Double d = new Double(); you are now given access to whatever methods are inside of the Double class.
I know these facts but I feel like I don't really understand what they actually MEAN. Could someone give an example of where a static class is absolutely necessary and one where creating an instance of a class is absolutely necessary?
Think of a class like a set of blueprints. Instantiating a class is like taking the blueprints and building the item. When an engineer designs a car, he comes up with the design. That would be the class. After the car is designed, the plans are handed off to the assembly line to be built. Each car that rolls off the line would be an instance of that design.
When the car is still just a design, you can't really do anything with it. You can't open its door if there's no car. Once you have the instance of a car, you can manipulate it. You can open the door, start the engine, etc. The same goes for a class like Double. Once you have the instance, you can manipulate it.
A static class, like Console, are classes that don't have instances. They're more like a way to group useful related functionality. In the case of Console, the functionality is used to interact with the command line. Math is used to group mathematics related code. Configuration is used to read/manipulate configuration files. None of these things require you to create anything unique for them to work.
A public class must be called in application by another class, for exampel this may be a class of data access (called by businnes layer).
A static class need not necessarily the creation of an instance for example tracing or logging class.
One (perhaps over) simplified example for thinking about static is the following:
If you have the class Dog; you could instantiate the class to create Dog Poodle = new Dog(); and Dog Labrador = new Dog();
If the Dog class has a variable hairColor, then for Poodle and Labrador, hairColor could be different. The two different instances are seperate.
If however, you added a static variable to Dog called numberOfDogs, and incremented the variable every time a new Dog was instantiated (you could do this is the constructor for example), then the variable would count the total number of Dogs, and would be the same number regardless of which instance of Dog you checked.
This is useful (and dangerous) depending on how you use it.

Access field from class where list belong to

let say i have following class:
class Shape
{
public int widht;
public List<Point> points;
}
and in class Point i want to use this widht property from class Shape, so if "point" belong to that list i wish to have possibility to use "container" properties. I also want to serialize then class Shape so I don't think i can use constructor with parameters.
Edit:
I will say how it looks like in my app:
i have class Device
class Device
{
string connection;
List<Task> tasks;
}
and Task
class Task
{
void DoTask()
{
and here i need the connection
}
}
so i just like to do it then foreach(task in task) task.DoTask() but i have to pass additional "this" like task.DoTask(this) or the connection where i think that i should have acces of my container if it allows me.
There's no general concept of the "owner" of an object. After all, the same Point reference could appear in several places. The desire to do this usually indicates a design smell. If you need to give the Point object more information, that's presumably when you're doing something with it - so pass that information to the appropriate method.
One of the simplest ways would be to build an explicit association between these two. For example:
public class Point {
Shape shape;
public Point( Shape shape ) {
this.shape = shape;
}
}
In this particular implementation each point points to a single shape. And you can of course access shape properties from within the point class.
The serialization should not an issue if you can control it.

C# a list or array that accepts all types?

I'm thinking of creating a class in XNA 3.1 that handles the drawing of shadows. I know there are lots of ways to do this but I'm wanting to do something like a List of all the objects that should have a shadow and pass that List to the shadow class so it iterates through each object and draws a shadow.
The reason I want to do it like this is cause I could easily control whether shadows exist or not with just a boolean.
A List for all types is probably unlikely, my backup is a List of type Object but I don't know how to cast the elements in the List which are of type Object back into their respective types so I can access their properties.
My second backup is make all the objects that will have shadows derive from a class called ShadowObject or something and make the List of that type. This is a really easy solution but the reason I'm not doing it yet is cause I don't like the idea of a dummy class just to make something work, but maybe I should start liking it.
My final backup would be to go into each class that will have shadows and have a boolean to see if shadows should be drawn and handle the drawing in the class itself, which I think shouldn't even be considered an option cause if I want to change the shadow mechanics I would have to change it in every class.
So I guess a List for all types is my official question for the public but I'm open to answers, suggestions, and criticism to my backup plans.
Edit: I'm aware of interfaces but my response to that is in the comments for xixonia's answer and after reading up a little more on interfaces I think having a ShadowCaster class would be more appropriate. It can handle all the shadow drawing because all shadows are drawn the same way, I don't need to define it for each object individually like an interface would require me to.
I believe you should use an interface, and make sure all of your "DrawShadow" methods match that interface. This way you can create a list of shadow casters that match the interface.
So long as an object implements that interface, you know you can tell it to draw a shadow. The actual drawing of the shadow will be left up to the object itself, provided the correct device to draw with.
For example:
class Program
{
public static void Main()
{
var shadowCasters = new List<ICastShadow>();
shadowCasters.Add(new Car());
shadowCasters.Add(new Plane());
var castShadows = true;
if (castShadows)
{
foreach (var caster in shadowCasters)
{
caster.DrawShadow(null);
}
}
Console.Read();
}
public class Car : ICastShadow
{
public void DrawShadow(object device)
{
Console.WriteLine("Car Shadow!");
}
}
public class Plane : ICastShadow
{
public void DrawShadow(object device)
{
Console.WriteLine("Plane Shadow!");
}
}
public interface IShadowCaster
{
void DrawShadow(object device);
}
}
When you need to test if your object is capable of casting shadows, you can use the "is" keyword...
if(myTrain is ICastShadow)
{
shadowCasters.Add(myTrain);
}
Hope this helps! :)
edit:
The reason you wouldn't want to use inheritance is if your game objects all draw shadows in different ways, and if some of your derived classes don't cast shadows. For instance:
You have a BrickBuilding and a GlassBuilding. Brick building should cast a shadow, and glass building should not. They both inherit from Building, which inherits from ShadowCaster. Even if all of your shadow-casting classes drew shadows the same way, you would still need to make ShadowCaster's methods virtual, so GlassBuilding could override them and do nothing when that method is called.
Using composition instead of inheritance (i.e: use an interface), you would be able to compose the shadow drawing method on only those classes that actually cast shadows, and you have one less class in your hierarchy (which makes maintainability a breeze).
So what happens when you use an interface and you start repeating the same logic over and over again because your shadow drawing classes all draw shadows the same way? Obviously this isn't the best idea. But if they're all drawing shadows the same way, you can use another class to draw shadows for them. Then comes the "ShadowCaster" class.
The shadow drawing implementation on each object would then call a method on this ShadowCaster to draw the shadow for it. This allows each object the option of drawing shadows in a different way, but also provides a way for each object to use the default shadow drawing implementation. It also provides a way to easily add and remove the ability to draw shadows for specific objects (simple don't let the objects implement the ICastShadow interface).
To take it one step further, you could treat shadow casting just like another drawing method, and create a generalized interface for drawing shadows / particles / reflections / tron-glow, etc, and created different "modules" that do these different things. Instead of having you class implement 'ICastShadows", have it implement "IDrawModules", and then give each class the correct modules at run time.
In other words, you can add a "CastShadow" module to BrickBuilding, and add a "Reflect" module to GlassBuilding, and have your code call "DrawModules" on both objects (from the IDrawModules interface).
Ok this is getting really really long, Hope this helps, and it's not too confusing.
I would suggest reading the first couple chapters of Head First Design Patterns. It's a java-based book, but the principles are the same for most languages.
Instead of a "dummy class" ShadowObject why don't you just create an interface IShadowObject that would expose all necessary methods and use:
List<IShadowObject>
i don't know much about game development but it looks like System.Generic.Collection.List is supported by the XNA framework. That would be your list of any type.
you can use "is" operator to check for type.
public bool check(object obj)
{
return obj is ShadowStuff;
// or obj.GetType() == ShadowStuff
}
to cast :
(ShawdowStuff) obj ;

Categories

Resources