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.
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.
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.
Sounds like silly idea but I was wondering if it's possible somehow.
Is it possible to change the base class of a derived class at runtime? Of course, there are lot of ifs and buts and the the question of why would someone do it and its a bad design probably and all that.
Keeping all those aside (even though they might be perfectly valid), let's say, just for kicks or to show your nerdiness, is it possible in C# or any language for that matter?
So something like:
public class baseOriginal {
public string justAProperty;
}
public class baseSwapped {
public int sillyNumber;
}
public class derivedClass : baseOriginal {
public bool iAmDumb;
}
void Main() {
baseOriginal derived = new derivedClass ();
Console.WriteLine(derived.justAProperty);
baseSwapped derivedSwapped = (??);
Console.WriteLine(derivedSwapped.sillyNumber);
}
It isn't possible in C#. Probably what you want is more of a prototype-based solution commonly found in dynamic languages like JavaScript where you can "extend" the functionality of the object by adding to how it's defined.
But to accomplish what your code hints at doing, you can have the swappable classes inherit from a common ancestor class. That way you can assign instances of each to their decendents.
public class baseClassAncestor{
}
public class baseOriginal:baseClassAncestor {
public string justAProperty;
}
public class baseSwapped:baseClassAncestor {
public int sillyNumber;
}
public class derivedClass : baseOriginal {
public bool iAmDumb;
}
You can do one time base class swap by loading different assemblies that implement base class BEFORE using derived class. But this approach will not make your exact code working as you will not be able to compile that - but moving access to methods of different base classes to separate functions could be made working.
You add UnionBase class that contains all possible methods/properties from all base classes so you can compile your Main code against the assembly with this class. Than at run time you load assembly that has contains your particular base class.
Usual warning: You need to have very good reasons and understanding for going this route. I.e. existing external code is a reason to consider such approach.
"Don't do it at home, performed on a closed course by trained professional".
One more possible workaround could be implemented using some AOP solution that is based on compile-time weaving, i.e. PostSharp, which is able to seamlessly inject new methods and interfaces to existing types as well as modify (intercept) existing ones.
There is actually a good reason where you may want to swap the base class. Let say you want to modify the base class but you don't wan't to perturb the current code base as it is shared among other teams. Let say there are 10+ derived class that inherits from base. You could create 10+ custom derived classes to override the base class but that is a lot of work. Here is what you do. The key to the problem is to create an interface and a base proxy class.
class Program
{
static void Main(string[] args)
{
IActionable action = new Derived<Base1>();
action.open();
action = new Derived<Base2>();
action.open();
}
}
// Proxybase is a fake base class. ProxyBase will point to a real base1 or
// base2
public class Derived<T>:ProxyBase,IActionable
{
public Derived():base(typeof(T))
// the open function is not overriden in this case allowing
// the base implementation to be used
}
// this looks like the real base class but it is a fake
// The proxy simply points to the implementation of base1 or base2 instead
public abstract class ProxyBase: IActionable
{
IActionable obj;
public ProxyBase(Type type,params object[] args)
{
obj = (IActionable)Activator.CreateInstance(type,args);
}
public virtual void open()
{
obj.open();
}
}
// notice base1 and base2 are NOT abstract in this case
// consider this the original implementation of the base class
public class Base1: IActionable
{
public virtual void open()
{
Console.WriteLine("base1 open");
}
}
// here base2 acquired the functionality of base1 and hides base1's open
function
// consider this implementation the new one to replace the original one
public class Base2: Base1, IActionable
{
public new virtual void open()
{
Console.WriteLine("base2 open");
}
}
public interface IActionable
{
void open();
}
The result would be as follows
base1 open
base2 open
UPDATE:
Although this answer works, the reality is that inheritance introduces coupling which makes this exercise difficult at best. Also, in a practical scenario, your requirements may lead you to want to derive from multiple base class which is not possible in c#. If you want to interchange the base class you are best to use the bridge design pattern (which in fact avoids inheritance altogether thus avoiding the coupling).
The closest thing I can think of is the following:
http://msdn.microsoft.com/en-us/library/dd264736.aspx
static void Main(string[] args)
{
ExampleClass ec = new ExampleClass();
// The following line causes a compiler error if exampleMethod1 has only
// one parameter.
//ec.exampleMethod1(10, 4);
dynamic dynamic_ec = new ExampleClass();
// The following line is not identified as an error by the
// compiler, but it causes a run-time exception.
dynamic_ec.exampleMethod1(10, 4);
// The following calls also do not cause compiler errors, whether
// appropriate methods exist or not.
dynamic_ec.someMethod("some argument", 7, null);
dynamic_ec.nonexistentMethod();
}
class ExampleClass
{
public ExampleClass() { }
public ExampleClass(int v) { }
public void exampleMethod1(int i) { }
public void exampleMethod2(string str) { }
}
I have no idea if the dynamic language runtime can do what you want it to do.
Closest you could get would be to
derive from both types by defining at
least one as an interface, then
casting derived from one to the other.
I would have to agree, based on the example this suggestion would satisfy what he wants to do, it also is a better design then what he actually wants to do.
Closest you could get would be to derive from both types by defining at least one as an interface, then casting derived from one to the other.
In C#, a superclass's static members are "inherited" into the subclasses scope. For instance:
class A { public static int M() { return 1; } }
class B : A {}
class C : A { public new static int M() { return 2; } }
[...]
A.M(); //returns 1
B.M(); //returns 1 - this is equivalent to A.M()
C.M(); //returns 2 - this is not equivalent to A.M()
Now, you can't inherit static classes, and the only place I can imagine that static inheritance might matter ignores it entirely: although you can make a generic constraint that requires a type parameter T to be a subclass of A, you still cannot call T.M() (which probably simplifies things for the VM), let alone write a different M implementation in a subclass and use that.
So, the "inheritance" of static members merely looks like namespace pollution; even if you explicitly qualify the name (i.e. B.M) A's version is still resolved.
Edit compare with namespaces:
namespace N1{ class X(); }
namespace N1.N2 { class X(); }
namespace N1.N2.N3 { [...] }
Within N1.N2.N3 It makes sense that if I use X without qualification it refers to N1.N2.X. But if I explicitly refer to N1.N2.N3.X - and no such class exists - I don't expect it to find N2's version; and indeed to compiler reports an error if you try this. By contrast, if I explicitly refer to B.M(), why doesn't the compiler report an error? After all, there's no "M" method in "B"...
What purpose does this inheritance have? Can this feature be used constructively somehow?
So, the "inheritance" of static
members merely looks like namespace
pollution
That's right, except that one guy's pollution is another guy's added spicy flavouring.
I think Martin Fowler, in his work on DSLs, has suggested using inheritance in this way to allow convenient access to static methods, allowing those methods to be used without class name qualification. So the calling code has to be in a class that inherits the class in which the methods are defined. (I think it's a rotten idea.)
In my opinion, static members should not be mixed into a class with a non-static purpose, and the issue you raise here is part of the reason why it's important not to mix them.
Hiding private static mutable data inside the implementation of an otherwise "instancey" class is particularly horrible. But then there are static methods, which are even worse mixers. Here's a typical use of static methods mixed into a class:
public class Thing
{
// typical per-instance stuff
int _member1;
protected virtual void Foo() { ... }
public void Bar() { ... }
// factory method
public static Thing Make()
{
return new Thing();
}
}
It's the static factory method pattern. It's pointless most of the time, but even worse is that now we have this:
public class AnotherThing : Thing { }
This now has a static Make method which returns a Thing, not a AnotherThing.
This kind of mismatch strongly implies that anything with static methods should be sealed. Static members fail to integrate well with inheritance. It makes no sense to have them heritable. So I keep static things in separate static classes, and I gripe about redundantly having to declare every member static when I've already said that the class is static.
But it's just one of those too-late-now things. All real, working languages (and libraries, and products) have a few of them. C# has remarkably few.
I rather have access to all my based static members in derived classes.
Otherwise i would need to know exactly where the static member was defined and call it explicitly.
When using Intellisense you can automatically know every static member available to that kind of class.
Of course, they are not inherited, it's just a shortcut
That's how it works, would probably just be a stupid answer in most cases. But in this case, it is how it works; since you derive from A you say that you are A + the extra features you add.
Therefore you need to be able to access the same variables that you would through an instance of A.
However, inheriting a static class makes no sense while access to the static members / fields / methods does.
An example of this is the following:
internal class BaseUser
{
public static string DefaultUserPool { get; set; }
}
internal class User : BaseUser
{
public int Id { get; set; }
public string Name { get; set; }
public User Parent { get; set; }
}
Where the test looks like this:
User.DefaultUserPool = "Test";
BaseUser.DefaultUserPool = "Second Test";
Console.WriteLine(User.DefaultUserPool);
Console.WriteLine(BaseUser.DefaultUserPool);
Both of the WriteLines outputs "Second Test", this is because both BaseUser and User should use DefaultUserPool, by design. And overriding static implemented methods wouldn't make mucn sense since it's just an accessor in the child-class.
There can be only one. Overriding it would mean that there's a new implementation for that sub-class, which would kill the term "static".
Actually, as I understand it, this is just a shortcut provided by the compiler. Syntax sugar. B.M() will just compile to A.M() since B does not have a static M() and A does. It's for easier writing, nothing else. There is no "static inheritance".
Added: And the requirement for new when "redefining" is just so that you don't accidentally shoot yourself in the foot.
I think it's for accessing protected static members of the base class.
class Base
{
protected static void Helper(string s)
{
Console.WriteLine(s);
}
}
class Subclass : Base
{
public void Run()
{
Helper("From the subclass");
}
}
So... What's the alternative?
The question mentions...
why doesn't the compiler report an error? After all, there's no "M" method in "B"...
But there is a derived "M" method in "B" class.
If the compiler did not present the programmer a unified virtual table for base cases, then the programmer would have to go hunting through base types to find static methods. This would break polymorphism.
Wikipedia...
Subtype polymorphism, almost universally called just polymorphism in the context of object-oriented programming, is the ability of one type, A, to appear as and be used like another type, B....
In strongly typed languages, polymorphism usually means that type A somehow derives from type B, or type C implements an interface that represents type B.
I always see it a means of preventing any form of polymorphism by the inheriting class on those items that you wish to retain the same function for all child classes.
ignore the above for some reason I was thinking of sealed instead of static
I suppose that you'd use static member variables and functions in order to ensure that any data or functionallity is not dependent on the a class instance as it would be instantiated only the once.
An example of use would be say a counter value that would keep a live count of all instances of a superclass's subclasses (each subclass increments the static count value on construction). This count value would be available and equal for all instances of the subclass.
I recently ran into a problem where it seems I need a 'static abstract' method. I know why it is impossible, but how can I work around this limitation?
For example I have an abstract class which has a description string. Since this string is common for all instances, it is marked as static, but I want to require that all classes derived from this class provide their own Description property so I marked it as abstract:
abstract class AbstractBase
{
...
public static abstract string Description{get;}
...
}
It won't compile of course. I thought of using interfaces but interfaces may not contain static method signatures.
Should I make it simply non-static, and always get an instance to get that class specific information?
Any ideas?
You can't.
The place to do this is with Attributes.
Eg
[Name("FooClass")]
class Foo
{
}
If you don't mind deferring to implementations to sensibly implement the Description property, you can simply do
public abstract string ClassDescription {get; }
// ClassDescription is more intention-revealing than Description
And implementing classes would do something like this:
static string classDescription="My Description for this class";
override string ClassDescription { get { return classDescription; } }
Then, your classes are required to follow the contract of having a description, but you leave it to them to do it sensibly. There's no way of specifying an implementation in an object-oriented fashion (except through cruel, fragile hacks).
However, in my mind this Description is class metadata, so I would prefer to use the attribute mechanism as others have described. If you are particularly worried about multiple uses of reflection, create an object which reflects over the attribute that you're concerned with, and store a dictionary between the Type and the Description. That will minimize the reflection (other than run time type inspection, which isn't all that bad). The dictionary can be stored as a member of whatever class that typically needs this information, or, if clients across the domain require it, via a singleton or context object.
If it is static, there is only one instance of the variable, I don't see how inheritance would make sense if we could do what you want to accomplish with static vars in derived classes. Personally I think you are going to far to try to avoid a instance var.
Why not just the classic way?
abstract class AbstractBase
{
protected string _Description = "I am boring abstract default value";
}
class Foo : AbstractBase {
public Foo() {
_Description = "I am foo!";
}
}
Combining static and abstract is somewhat meaningless, yes. The idea behind static is one need not present an instance of the class in order to use the member in question; however with abstract, one expects an instance to be of a derived class that provides a concrete implementation.
I can see why you'd want this sort of combination, but the fact is the only effect would be to deny the implementation use of 'this' or any non-static members. That is, the parent class would dictate a restriction in the implementation of the derived class, even though there's no underlying difference between calling an abstract or 'static abstract' member (as both would need a concrete instance to figure out what implementation to use)
A possible workaround is to define a Singleton of your derived class in your base class with the help of Generics.
import System;
public abstract class AbstractBase<T>
where T : AbstractBase<T>, new()
{
private static T _instance = new T();
public abstract string Description { get; }
public static string GetDescription()
{
return _instance.Description;
}
}
public class DerivedClass : AbstractBase<DerivedClass>
{
public override string Description => "This is the derived Class";
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(DerivedClass.GetDescription());
Console.ReadKey();
}
}
The trick is to tell your AbstractBase<T> some details about how DerivedClass is implemented:
It is newable with where T: new() so it can create a Singleton instance
It derives from itself with where T : AbstractBase<T> so it knows that there will be a implementation of Description
This way _instance contains the Description field which can be called in the static Method GetDescription().
This forces you to overwrite Descriptionin your DerivedClass and allows you to call its value with DerivedClass.GetDescription()
It's not static if it has to be called on an instance.
If you're not calling it on an instance, then there's no polymorphism at play (i.e. ChildA.Description is completely unrelated to ChildB.Description as far as the language is concerned).
You can...
In the abstract class...
protected abstract InWindow WindowInstance { get; set; }
In the derived class...
private static InWindow _instance;
protected override InWindow WindowInstance
{
get => _instance;
set => _instance = value;
}
You could make the "abstract" base method throw an Exception, so then a developer is "warned" if he tries to invoke this method on a child class without overriding.
The downside is that one might extend the class and not use this method. Then refer to other answers provided.