Reputation: 53307
Imagine you're making a game object that is using some texture:
public class Action {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/select";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public static Texture2D cursor { get { return ResourceManager.loadTexture(ref cursorTex, HoverCursor); } }
}
The loadTexture
function will load the texture if null
is passed. otherwise, it just returns the original value.
As you can see, I'm making an Action prototype. There will be actions like Attack, Move or Build. I want to store one (and different) texture object per class definition. This object shall be lazy-loaded when needed using the getter above.
Since the static property can't be overriden, how can I implement this for all children instances?
Here's the loadTexture
:
public static Texture2D loadTexture(ref Texture2D target, string name)
{
if (target == null)
{
target = (Texture2D)Resources.Load(name, typeof(Texture2D));
}
return target;
}
Upvotes: 1
Views: 1031
Reputation: 70701
You've practically answered the question yourself:
Since the static property can't be overriden, how can I implement this for all children instances?
Just make the property an instance property. For example:
public class Action {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/select";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public virtual Texture2D cursor
{
get
{
return ResourceManager.loadTexture(ref cursorTex, HoverCursor);
}
}
}
public class Attack {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/attack";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public override Texture2D cursor
{
get
{
return ResourceManager.loadTexture(ref cursorTex, HoverCursor);
}
}
}
You would still save just one texture per class, but given an instance of each class you'll be able to retrieve the correct cursor texture for that class. Presumably you need to set the cursor only when there's an instance of the class around anyway, so this shouldn't be an unreasonable limitation.
Note in the above that if no other code actually needs the HoverCursor
property, you can get rid of it, make the _HoverCursor
const a private member, and then use that directly in the cursor
property getter.
Also note that this implementation isn't thread-safe. As long as you're always accessing the cursor
property from a single thread, that's fine. But if not (or perhaps just for the simplicity) you may prefer using the Lazy<T>
class. For example:
//This is the get texture by string
private static Lazy<Texture2D> cursorTex =
new Lazy<Texture2D>(() => ResourceManager.loadTexture(HoverCursor));
public virtual Texture2D cursor
{
get
{
return cursorTex.Value;
}
}
In this version, note that the loadTexture()
method has changed to always load the texture, and thus does not need the ref
parameter. The Lazy<T>
class will ensure thread-safe lazy initialization, calling loadTexture()
only once per class.
Upvotes: 1
Reputation: 64943
You can use inheritance and polymorphism with instance members, and use a static factory method as a façade to simplify the instantiation of the implementation.
For example
public abstract class Action
{
public abstract void LoadTexture(...);
}
// Since static façade class has a generic type parameter, we're talking
// about a completely different class than just "Action" and both can co-exist!
public static class Action<TAction> where TAction : Action, new()
{
public static Texture2D LoadTexture(...)
{
// Since generic TAction parameter must implement a public parameterless
// constructor, you may instantiate T like a concrete class:
return new TAction().LoadTexture(...);
}
}
Thus, you would use the static method as follows:
Texture2D texture = Action<CustomAction>.LoadTexture2D(...);
Upvotes: 1