So I have a base set of abstract classes using BaseEngine namespace, and the real game project deriving the set.
There are many base classes that have a set of abstract methods and predefined methods such as:
Item, Entity, Skill
public abstract class Item
{
public string name;
public void DestroyItemInBaseEngine ()
{
// bunch of codes
}
public abstract void BakeItemTheWayYouWant ();
}
public abstract class SkillManager
{
public abstract T InteractItemWithSkill<T> (T item)
where T:Item, new(); //not sure if this particular line is valid, but this was written just to help you understand
}
And deriving classes such as:
public class GameItem : Item
{
public int variableSpecificToThisGameProject;
// and other implementation for this specific game...
}
Now, Within BaseEngine, it would have abstract classes that refer Item multiple times in managers like BaseItemManager. Each game would manage differently so these managers must be derived as well. When a specific game project derives BaseItemManager, it would have to use GameItem.
BaseEngine was created to be able to be used with different projects, a basically set of abstract classes.
Every time when these derived objects are being referred in the game project, you either have to cast it, or use generic type in abstract methods like such:
if (ValidateItemObject<GameItem> (GameItem item) != null)
// do something with it
So because GameItem and other types are decided at compile time, is there anyway to declare something like T = GameItem, S = GameSkill for the entire project so we don't have to mention every time related methods (like above) or classes are called?
I tried my best to make my case as clear as possible, but let me know if isn't clear what I'm trying to do.
EDIT:
protected abstract T ConvertTableToItem<T> (T item, LuaTable luaTable) where T:BaseItem;
protected override ProjectItem SetItemAPI<ProjectItem> (ProjectItem newItem, LuaTable luaTable)
{
newItem.desc = "test";
}
This wouldn't work saying desc is not a member of the class. I can guarantee that it is. desc (public string desc) is defined in ProjectItem.
ProjectItem is a derived class of BaseItem.
If you want to declare a class with a fixed type parameter for a generic type, the simplest thing is to just inherit the generic type while specifying the type parameter you want. For example:
static class SomeSpecificClass : SomeBaseClass<GameItem> { ... }
Then any method in SomeBaseClass<T> that depends on the type parameter T can be called via SomeSpecificClass without specifying the type parameter T.
That said, the other tool in your toolbox that would probably address at least the example you provided is to take advantage of C#'s type inference for generic methods.
For example, if you have a base-class generic method like this:
class SomeBaseClass
{
public static T ValidateItemObject<T>(T item) where T : Item
{
// ...something
}
}
Then you don't actually need to use the type parameter when calling the method, as long as the parameter you pass is correctly typed. For example:
GameItem gameItem = ...;
if (SomeBaseClass.ValidateItemObject(gameItem) != null)
{
// ...something
}
(Naturally, if the code is in a class that inherits SomeBaseClass, then you don't actually need to specify the class name when calling the method).
Unfortunately, your actual code example is fairly vague. But based on the comment to the question and your reply, it seems like the above should address your question. If not, please consider editing your question to provide a more specific, complete, but minimal code example, as well as a clear description of what that example does now, and how you would like it to change. You may also want to read https://stackoverflow.com/help/how-to-ask for tips on improving the clarity of the question.
Related
I'm not sure if this is a strange thing to do or not, or if it is some how code smell...but I was wondering if there was a way (some sort of oop pattern would be nice) to "cast" a base type to a form of its derived type. I know this makes little sense as the derived type will have additional functionality that the parent doesn't offer which is in its self not fundamentally sound. But is there some way to do this? Here is a code example to so I can better explain what I"m asking.
public class SomeBaseClass {
public string GetBaseClassName {get;set;}
public bool BooleanEvaluator {get;set;}
}
public class SomeDerivedClass : SomeBaseClass {
public void Insert(SqlConnection connection) {
//...random connection stuff
cmd.Parameters["IsItTrue"].Value = this.BooleanEvalutar;
//...
}
}
public static void Main(object[] args) {
SomeBaseClass baseClass = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)baseClass;
derClass.Insert(new sqlConnection());
}
I know this seems goofy but is there any way to accomplish something of this sort?
Not soundly, in "managed" languages. This is downcasting, and there is no sane down way to handle it, for exactly the reason you described (subclasses provide more than base classes - where does this "more" come from?). If you really want a similar behaviour for a particular hierarchy, you could use constructors for derived types that will take the base type as a prototype.
One could build something with reflection that handled the simple cases (more specific types that have no addition state). In general, just redesign to avoid the problem.
Edit: Woops, can't write conversion operators between base/derived types. An oddity of Microsoft trying to "protect you" against yourself. Ah well, at least they're no where near as bad as Sun.
Try composition instead of inheritance!
It seems to me like you'd be better off passing an instance of SomeBaseClass to the SomeDerivedClass (which will no longer derive base class, and should be renamed as such)
public class BooleanHolder{
public bool BooleanEvaluator {get;set;}
}
public class DatabaseInserter{
BooleanHolder holder;
public DatabaseInserter(BooleanHolder holder){
this.holder = holder;
}
public void Insert(SqlConnection connection) {
...random connection stuff
cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
...
}
}
public static void Main(object[] args) {
BooleanHolder h = new BooleanHolder();
DatabaseInserter derClass = new DatabaseInserter(h);
derClass.Insert(new sqlConnection);
}
Check out http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html (page 3):
Code reuse via composition Composition
provides an alternative way for Apple
to reuse Fruit's implementation of
peel(). Instead of extending Fruit,
Apple can hold a reference to a Fruit
instance and define its own peel()
method that simply invokes peel() on
the Fruit.
Personally I don't think it's worth the hassle of using Inheritance in this case. Instead just pass the base class instance in in the constructor and access it through a member variable.
private class ExtendedClass //: BaseClass - like to inherit but can't
{
public readonly BaseClass bc = null;
public ExtendedClass(BaseClass b)
{
this.bc = b;
}
public int ExtendedProperty
{
get
{
}
}
}
Downcasting makes sense, if you have an Object of derived class but it's referenced by a reference of base class type and for some reason You want it back to be referenced by a derived class type reference. In other words You can downcast to reverse the effect of previous upcasting. But You can't have an object of base class referenced by a reference of a derived class type.
I'm not saying I recommend this. But you could turn base class into JSON string and then convert it to the derived class.
SomeDerivedClass layer = JsonConvert.DeserializeObject<SomeDerivedClass>(JsonConvert.SerializeObject(BaseClassObject));
No, this is not possible. In a managed language like C#, it just won't work. The runtime won't allow it, even if the compiler lets it through.
You said yourself that this seems goofy:
SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class;
So ask yourself, is class actually an instance of SomeDerivedClass? No, so the conversion makes no sense. If you need to convert SomeBaseClass to SomeDerivedClass, then you should provide some kind of conversion, either a constructor or a conversion method.
It sounds as if your class hierarchy needs some work, though. In general, it shouldn't be possible to convert a base class instance into a derived class instance. There should generally be data and/or functionality that do not apply to the base class. If the derived class functionality applies to all instances of the base class, then it should either be rolled up into the base class or pulled into a new class that is not part of the base class hierarchy.
C# language doesn't permit such operators, but you can still write them and they work:
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) { ... }
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) { ... }
Yes - this is a code smell, and pretty much nails down the fact that your inheritance chain is broken.
My guess (from the limited sample) is that you'd rather have DerivedClass operate on an instance of SomeBaseClass - so that "DerivedClass has a SomeBaseClass", rather than "DerivedClass is a SomeBaseClass". This is known as "favor composition over inheritance".
As others have noted, the casting you suggest is not really possible.
Would it maybe be a case where the Decorator pattern(Head First extract) can be introduced?
Have you thought about an interface that what is currently your base class and your derived class both would implement? I don't know the specifics of why you're implementing this way but it might work.
This is called downcasting and Seldaek's suggestion to use the "safe" version is sound.
Here's a pretty decent description with code samples.
This is not possible because how are you going to get the "extra" that the derived class has. How would the compiler know that you mean derivedClass1 and not derivedClass2 when you instantiate it?
I think what you are really looking for is the factory pattern or similar so you can instantiate objects without really knowing the explicit type that's being instantiate. In your example, having the "Insert" method would be an interface that instance the factory returns implements.
I dont know why no one has said this and i may have miss something but you can use the as keyword and if you need to do an if statement use if.
SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
;
-edit- I asked this question long ago
I've recently been in the need of extending a simple DTO with a derived type in order to put some more properties on it. I then wanted to reuse some conversion logic I had, from internal database types to the DTOs.
The way I solved it was by enforcing an empty constructor on the DTO classes, using it like this:
class InternalDbType {
public string Name { get; set; }
public DateTime Date { get; set; }
// Many more properties here...
}
class SimpleDTO {
public string Name { get; set; }
// Many more properties here...
}
class ComplexDTO : SimpleDTO {
public string Date { get; set; }
}
static class InternalDbTypeExtensions {
public static TDto ToDto<TDto>(this InternalDbType obj) where TDto : SimpleDTO, new() {
var dto = new TDto {
Name = obj.Name
}
}
}
I can then reuse the conversion logic from the simple DTO when converting to the complex one. Of course, I will have to fill in the properties of the complex type in some other way, but with many, many properties of the simple DTO, this really simplifies things IMO.
That cannot work. Go look at the help page linked by the compile error.
The best solution is to use factory methods here.
As many answers have pointed out, you can't downcast which makes total sense.
However, in your case, SomeDerivedClass doesn't have properties that will be 'missing'. So you could create an extension method like this:
public static T ToDerived<T>(this SomeBaseClass baseClass)
where T:SomeBaseClass, new()
{
return new T()
{
BooleanEvaluator = baseClass.BooleanEvaluator,
GetBaseClassName = baseClass.GetBaseClassName
};
}
So you aren't casting, just converting:
SomeBaseClass b = new SomeBaseClass();
SomeDerivedClass c = b.ToDerived<SomeDerivedClass>();
This only really works if all of the data in the base class is in the form of readable and writable properties.
C++ handles it using a constructor. C++ Typecasting. It seems like an oversight to me. Many of you have brought up the issue of what would the process do with the extra properties. I would answer, what does the compiler do when it creates the derived class when the programmer does not set the properties? I have handled this situation similar to C++. I create a constructor that takes the base class then manually set the properties in the constructor. This is definitely preferable to setting a variable in the derived class and breaking the inheritance. I would also choose it over a factory method because I think the resulting code would be cleaner looking.
Let's say I have an interface that many many distinct classes implement:
public interface IHaveObjects
{
object firstObject();
}
(Note: I can't make it an abstract base class as implementors of IHaveObjects may already have a base class.)
Now I want to add a new method to the interface, so that one implementer of the interface can have special behaviour for it. Ideally I would do something like this:
public interface IHaveObjects
{
object firstObject();
object firstObjectOrFallback()
{
return firstObject();
}
}
then go to that one implementor of the interface and give it the override:
public class ObjectHaverPlus : IHaveObjects
{
public override object IHaveObjects.firstObjectOrFallback()
{
return firstObject() ?? getDefault();
}
}
However it is forbidden in C# to provide a method body in an interface, and I would like to avoid going to every single implementer of IHaveObjects to drop in a definition of firstObjectOrFallback(). (Imagine if there are hundreds or thousands)
Is there a way to do this without lots of copy paste?
How about introducing a second interface which inherits from IHaveObjects.
Than you only have to change these classes, which need the new interface with the new method.
This looks like:
interface I1
{
void Method1();
}
interface I2 : I1
{
void Method2();
}
That's the problem with interfaces - they don't have any default implementation so any changes to them are breaking changes - i.e. code needs to be modified to work with new version of interface.
Since your implementations already have base classes on their own - you cannot turn it into abstract class, nor does C# have multiple class inheritance.
What you can do is to think - is it really a method on interface? Or could it be implemented as an extension method on interface (didn't try that but I suppose it will work just fine)?
If it is a method on interface and it should stay there - you may think of breaking this interface into two parts, second inheriting from the first (IHaveObjectsAndSupportDefault : IHaveObjects) and use this interface where default value is truly needed (like some other answers indicate).
I may have misunderstood your question, but why not use a second interface, something like:
public interface IHaveObjectsEnhanced
{
object FirstObjectOrFallback();
}
Then you could implement the first and second interface:
public class ObjectHaverPlus : IHaveObjects, IHaveObjectsEnhanced
{
public object FirstObject()
{
}
public object FirstObjectOrFallback()
{
return FirstObject() ?? GetDefault();
}
}
I have been making some hamfisted attempts to apply correct OOP principles to my project. I have an abstract class called DocumentSection, and several classes deriving from it (DocumentSectionView, DocumentSectionText, etc). Similarly I have an abstract class (DocAction) with several classes deriving from it (DocumentActionReplaceByTag, DocumentSectionAppend, etc). Each DocumentSection has a DocumentAction within it.
My understanding of all this inheritance business is that by specifying a 'DocumentAction', this would allow any of those derived classes to be put in its place, and that any properties/methods from the base class would be available, as well as any specified in the concrete class I instantiate. So in the below example, I expected to be able to see the PerformAction method (leaving the virtual/override keywords out of the mix for now). And it is available.
However, because I went v.DocAction = new DocumentActionReplaceByTag();, I would also have expected my ReplaceActionFindText property to be visible.
Obviously I've got it wrong somewhere - any comments appreciated.
class Program
{
static void Main(string[] args)
{
DocumentSectionView v = new DocumentSectionView();
v.DocAction = new DocumentActionReplaceByTag();
// would like to go:
//v.DocAction.ReplaceActionFindText...
Console.ReadLine();
}
}
public abstract class DocumentSection
{
public abstract string GetContent();
public DocumentAction DocAction { get; set; }
}
public class DocumentSectionView : DocumentSection
{
public string ViewPath { get; set; }
public dynamic ViewModel { get; set; }
public override string GetContent()
{
return "test";
}
}
public abstract class DocumentAction
{
void PerformAction(StringBuilder sb, string content);
}
public class DocumentActionReplaceByTag : DocumentAction
{
public string ReplaceActionFindText { get; set; }
public void PerformAction(StringBuilder sb, string content)
{
sb.Replace(ReplaceActionFindText, content);
}
}
EDIT:
I've marked an answer as correct, but thought I'd add the fruits of my further thought on this matter for those coming across this later:
a) As pointed out, my intentions were broadly right but my method wrong. Setting the 'Action's property from the Main method was not correct. In all cases, a a DocumentActionReplaceByTag requires the FindText so I placed it in the constructor:
public DocumentActionReplaceByTag(string replaceActionFindText)
{
this.ReplaceActionFindText = replaceActionFindText;
}
From then on, a constructor with 0 arguments will rightly fail, and prevent a case where the action is executed but no findtext is specified.
b) Polymorphism works fine now, because my extra property findtext has been populated, and running PerformAction will run correctly regardless of the action type.
Because you are assigning your derived class to a property with the type of the base class only the methods and properties of the base class will be available. And this makes sense since you could have assigned any instance of a class that derives from the base class - so any derived methods cannot be used in this context.
This is one of the OOP principles - your derived class instances may be used as an instance of a base class (but not the other way round)
Edit:
To elaborate on the solution proposed by #sll to cast to a particular derived class type: Don't do it! It is a workaround but not in the interest of the overall design.
If you have to cast to a derived type then you are violating the Liskov substitution principle meaning that any derived type should be usable in place of the base type - that's clearly not the case if you need a specific cast.
Rethink your design - do you really need a property with the base class type and if so are the methods currently only in one particular derived type better off being in the base type as well?
The v reference type is of the DocumentSectionView which is not aware of methods of the DocumentActionReplaceByTag class even underlying instance is of DocumentActionReplaceByTag as you've assigned it. You need to cast it to be able accesing derived class members:
((DocumentActionReplaceByTag)v.DocAction).ReplaceActionFindText
Also in some cases this is pretty fine when underlying instance could not be casted so some part of code should be skipped, then you can use exception-safe way of casting using as operator:
var typedAction = v.DocAction as DocumentActionReplaceByTag;
if (typedAction != null)
{
// accessing the typedAction.ReplaceActionFindText property
}
My suggestions are only to help you understand C# side of question, regarding overall design and approach please see BrokenGlass's answer.
No, in your example, since DocAction is only a DocumentAction, you will only be able to see the properties of a DocumentAction, no matter which derived type of DocumentAction is used.
Let's say I have a base class named BaseClass:
public BaseClase{
public bool isCool;
}
Now let's say I have two classes that inherit from BaseClass
public Class1: BaseClass{
public bool isGreen;
}
public Class2: BaseClass{
public bool isPurple;
}
Now let's say I want to create a list that contains instances of both Class1 and Class2 by creating a List;
var genericList = new List<BaseClass>();
Next, let's add an instance of Class1 and Class2 to genericList.
genericList.Add(new Class1());
genericList.Add(new Class2());
Now, here is what I have a question about. If I want to access Class1.IsGreen or Class2.IsPurple, I have to cast each item in genericList as Class1 or Class2.
foreach(var item in genericList){
if(item is Class1){
var temp = (Class1) item;
temp.IsGreen = true;
}
if(item is Class2){
var temp = (Class2) item;
item.IsPurple = true;
}
}
Is this just the way you're supposed to do things? It seems very clunky to me, and the complexity of the code I'm writing that uses this type of code structure is getting out of hand. I'm new to inheritance, and want to learn if this is just the way you're supposed to do things, or if there are better alternatives out there.
It really depends on what you are trying to do. If you can abstract out the property, so something like IsSelected, then you could expose it on your BaseClass as a virtual or abstract property. Then you wouldn't have to cast your items in your for-loop.
Or you could abstract it out to a abstract/virtual method, like UpdateColor(bool). Then each derived class could override that and set the appropriate property on themselves.
There are several other alternatives, including interfaces and extension methods, that you could use to make it cleaner.
There is basically no better alternative, although if you only want to operate on, say Class1's then you can use the OfType extension
var genericList = new List<BaseClass>();
genericList.Add(new Class1());
genericList.Add(new Class2());
foreach(var item in genericList.OfType<Class1>())
{
// no need to cast
item.IsGreen = true;
}
If you can abstarct somehow what are you doing in the cycle, for instance, you are applying a Default colors for an item, so expose method IEntity.SetDefaultColors(IColorInformation) and implement it in each item class.
BTW: Consider the Interface segregation principle and introduce a common interface for you entities like IEntity.
To better (or worse) illustrate, I'm going to change IsGreen to IsSpecial and IsPurple to MaximumHappiness--just so that we can be clear that the two properties represent two very different things.
One way to handle it would be to make them both properties of the base class (if applicable), so then you don't have to typecast them.
Another would be to provide a function to the base class (which the inheriting classes could override). For instance, the function could be called "DoSpecialThing" and inside of it you can access any properties on the child classes.
If the properties are guaranteed to be boolean (and represent some amount of related ideas), then you might be able to use flags. For instance:
[Flags]
enum MoodType
{
//Moods
Happy,
Sad,
Elated,
Overjoyed,
Depressed,
//Mental States
Confused,
Alert,
Sluggish,
//Other
Sleepy,
Awake
}
So now the base class could have a property called "State" or something and it can be any combination of the above flags. So you could indicate that an object is Sleepy, Confused, and Happy all in one property.
You can read more about flags (and decide if they're applicable to your situation) at this link.
I'd recommend this SO question, too. Specifically the top-voted (although unaccepted) answer.
I would say somethign like this, pseudoecode!:
public abstract BaseClase{
public bool isCool;
public abstract setColor();
}
public Class1: BaseClass{
public bool isGreen;
public override void SetColor() {IsGreen=true;}
}
public Class2: BaseClass{
public bool isPurple;
public override void SetColor() {IsPurple =true;}
}
foreach(var item in genericList){
item.SetColor();
}
Should work..
Regards.
I have a generic class Proxy<T>, and I want to write another generic class with its type parameter being a Proxy.
I want to write:
public class MyClass<U> where U : Proxy<T>
but the compiler reports The type or namespace name T could not be found.
A solution I've found is to declare it like this:
public class MyClass<U, T> where U : Proxy<T>
but this seems clumsy as the client will have to declare two type parameters, like this:
public class SomeClass { ... }
public class SomeProxy : Proxy<SomeClass> { ... }
and then in a client somewhere:
var proxyWrapper = new MyClass<SomeProxy, SomeClass>();
How can I do this without having to have two generic types on MyClass. After all, if we know the first is SomeProxy, it should follow that the second is SomeClass.
Maybe something like this would do the job, too?
class Test<T> {
public Test(Proxy<T> proxy) { this.MyProxy = proxy; }
public Proxy<T> MyProxy { get; private set; }
}
Sorry, you just can't do this in C# without having MyClass generic on both types (unless you want to use reflection to create instances of it.)
You can have an interface IMyClass<SomeProxy> and a factory method that creates and returns an instance of MyClass<SomeProxy, SomeClass>. You may need to create the instance using Reflection.
I have a code example here of a similar situation: the end user only cares about a single type parameter, but the implementation needs to have two. In my example, I don't have to use Reflection to create the instance, but it sounds like you may need to.
What you're trying to do is possible using compile-time constructs such as C++ templates, but not run-time constructs such as C# generics.
If you want T to remain generic in Myclass, then the MyClass instance still needs to resolve all internally used generic types and you HAVE TO declare it somewhere. The way to go is the verbose way you mentioned:
public class MyClass<U, T> where U : Proxy<T>
If you don't care about the generic type T in MyClass then create interface and use it instead:
public interface IProxy { ... }
public class SomeClass { ... }
public class SomeProxy : Proxy<SomeClass>, IProxy { ... }
public class MyClass<U> where U : IProxy
and then in a client somewhere:
var proxyWrapper = new MyClass<SomeProxy>();
But do note that you cannot use type T in your interface declaration and Type U is now more general then before.
It turns out that all of the SomeProxy classes I want to deal with actually just override one method of Proxy<T> which has the signature:
T LoadInternal(Identifier id)
So, what I've done is created an internal class inside MyClass which takes a Func<Identifier, T> in its constructor. I can then pass a Func<Identifier, T> as a parameter to the constructor of MyClass and use my subclass in place of SomeProxy.
Seems a bit convoluted, but it works for me. To summarise, I now have:
public class MyClass<T>{
private SomeProxy theProxy;
public MyClass(Func<Identifier, T> loadDelegate){
theProxy = new SomeProxy(loadDelegate);
}
/* Other methods here */
class SomeProxy : Proxy<T>{
private Func<Identifier, T> m_loadInternal;
public SomeProxy(Func<Identifier, T> loadInternal){
m_loadInternal = loadInternal;
}
protected override T LoadInternal(Identifier id){
return m_loadInternal(id);
}
}
}
So, from client code, instead of writing a class which extends Proxy and then overriding LoadInternal in that class, I just create MyClass using:
var myClass = new MyClass<T>(x => CodeWhichReturnsT());
How can I do this without having to have two generic types on MyClass. After all, if we know the first is SomeProxy, it should follow that the second is SomeClass.
Although you seem to have found an answer to the main part of the question, I figured I'd offer my understanding about this part. It sounds like you wish you could do something like this:
class Proxy<T>
{
T Value { get; set; }
}
class MyClass<U> where U : Proxy<> { }
and have the compiler fill in the Proxy type parameter when you provide U. Since you have declared U as inheriting from Proxy, you must intend to use one of the methods on Proxy, that probably use the T parameter, like so:
class MyClass<U> where U : Proxy<>
{
void SomeMethod(U parameter)
{
var local = parameter.Value;
//more code here...
}
}
Now, what is the compiler supposed to infer for local here? This is the main problem I see that makes such a feature, if possible, hard to implement. If you don't want to use any methods that use the generic type of Proxy, you could instead make a non-generic base class and use that for U and sidestep the entire problem.
I am not a compiler writer, but a couple possibilities of how this could be dealt with come to mind. It could just say object (or whatever other restriction you put on the type parameter in Proxy), but that doesn't seem quite right or quite what normal generics seem to do. This would also require the CLR to allow open generic types as a constraint on the generic parameter, which I doubt it does. The other option I could see is for the type to actually have the second type parameter, and the compiler to give you syntactic sugar to make it easier.
Any way you go, this feature seems like a lot of work for a little benefit in what is probably a rare scenario, thus not likely to make the cut to get implemented.