Related
What are differences between declaring a method in a base type "virtual" and then overriding it in a child type using the "override" keyword as opposed to simply using the "new" keyword when declaring the matching method in the child type?
I always find things like this more easily understood with pictures:
Again, taking joseph daigle's code,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
If you then call the code like this:
Foo a = new Bar();
a.DoSomething();
NOTE: The important thing is that our object is actually a Bar, but we are storing it in a variable of type Foo (this is similar to casting it)
Then the result will be as follows, depending on whether you used virtual/override or new when declaring your classes.
The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}
This prints false, if you used override it would have printed true.
(Base code taken from Joseph Daigle)
So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.
Here's some code to understand the difference in the behavior of virtual and non-virtual methods:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
The new keyword actually creates a completely new member that only exists on that specific type.
For instance
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
The method exists on both types. When you use reflection and get the members of type Bar, you will actually find 2 methods called DoSomething() that look exactly the same. By using new you effectively hide the implementation in the base class, so that when classes derive from Bar (in my example) the method call to base.DoSomething() goes to Bar and not Foo.
Beyond just the technical details, I think using virtual/override communicates a lot of semantic information on the design. When you declare a method virtual, you indicate that you expect that implementing classes may want to provide their own, non-default implementations. Omitting this in a base class, likewise, declares the expectation that the default method ought to suffice for all implementing classes. Similarly, one can use abstract declarations to force implementing classes to provide their own implementation. Again, I think this communicates a lot about how the programmer expects the code to be used. If I were writing both the base and implementing classes and found myself using new I'd seriously rethink the decision not to make the method virtual in the parent and declare my intent specifically.
virtual / override tells the compiler that the two methods are related and that in some circumstances when you would think you are calling the first (virtual) method it's actually correct to call the second (overridden) method instead. This is the foundation of polymorphism.
(new SubClass() as BaseClass).VirtualFoo()
Will call the SubClass's overriden VirtualFoo() method.
new tells the compiler that you are adding a method to a derived class with the same name as a method in the base class, but they have no relationship to each other.
(new SubClass() as BaseClass).NewBar()
Will call the BaseClass's NewBar() method, whereas:
(new SubClass()).NewBar()
Will call the SubClass's NewBar() method.
The difference between the override keyword and new keyword is that the former does method overriding and the later does method hiding.
Check out the folllowing links for more information...
MSDN and Other
new keyword is for Hiding. - means you are hiding your method at runtime. Output will be based base class method.
override for overriding. - means you are invoking your derived class method with the reference of base class. Output will be based on derived class method.
My version of explanation comes from using properties to help understand the differences.
override is simple enough, right ? The underlying type overrides the parent's.
new is perhaps the misleading (for me it was). With properties it's easier to understand:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
Using a debugger you can notice that Foo foo has 2 GetSomething properties, as it actually has 2 versions of the property, Foo's and Bar's, and to know which one to use, c# "picks" the property for the current type.
If you wanted to use the Bar's version, you would have used override or use Foo foo instead.
Bar bar has only 1, as it wants completely new behavior for GetSomething.
Not marking a method with anything means: Bind this method using the object's compile type, not runtime type (static binding).
Marking a method with virtual means: Bind this method using the object's runtime type, not compile time type (dynamic binding).
Marking a base class virtual method with override in derived class means: This is the method to be bound using the object's runtime type (dynamic binding).
Marking a base class virtual method with new in derived class means: This is a new method, that has no relation to the one with the same name in the base class and it should be bound using object's compile time type (static binding).
Not marking a base class virtual method in the derived class means: This method is marked as new (static binding).
Marking a method abstract means: This method is virtual, but I will not declare a body for it and its class is also abstract (dynamic binding).
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
}
What are differences between declaring a method in a base type "virtual" and then overriding it in a child type using the "override" keyword as opposed to simply using the "new" keyword when declaring the matching method in the child type?
I always find things like this more easily understood with pictures:
Again, taking joseph daigle's code,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
If you then call the code like this:
Foo a = new Bar();
a.DoSomething();
NOTE: The important thing is that our object is actually a Bar, but we are storing it in a variable of type Foo (this is similar to casting it)
Then the result will be as follows, depending on whether you used virtual/override or new when declaring your classes.
The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}
This prints false, if you used override it would have printed true.
(Base code taken from Joseph Daigle)
So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.
Here's some code to understand the difference in the behavior of virtual and non-virtual methods:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
The new keyword actually creates a completely new member that only exists on that specific type.
For instance
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
The method exists on both types. When you use reflection and get the members of type Bar, you will actually find 2 methods called DoSomething() that look exactly the same. By using new you effectively hide the implementation in the base class, so that when classes derive from Bar (in my example) the method call to base.DoSomething() goes to Bar and not Foo.
Beyond just the technical details, I think using virtual/override communicates a lot of semantic information on the design. When you declare a method virtual, you indicate that you expect that implementing classes may want to provide their own, non-default implementations. Omitting this in a base class, likewise, declares the expectation that the default method ought to suffice for all implementing classes. Similarly, one can use abstract declarations to force implementing classes to provide their own implementation. Again, I think this communicates a lot about how the programmer expects the code to be used. If I were writing both the base and implementing classes and found myself using new I'd seriously rethink the decision not to make the method virtual in the parent and declare my intent specifically.
virtual / override tells the compiler that the two methods are related and that in some circumstances when you would think you are calling the first (virtual) method it's actually correct to call the second (overridden) method instead. This is the foundation of polymorphism.
(new SubClass() as BaseClass).VirtualFoo()
Will call the SubClass's overriden VirtualFoo() method.
new tells the compiler that you are adding a method to a derived class with the same name as a method in the base class, but they have no relationship to each other.
(new SubClass() as BaseClass).NewBar()
Will call the BaseClass's NewBar() method, whereas:
(new SubClass()).NewBar()
Will call the SubClass's NewBar() method.
The difference between the override keyword and new keyword is that the former does method overriding and the later does method hiding.
Check out the folllowing links for more information...
MSDN and Other
new keyword is for Hiding. - means you are hiding your method at runtime. Output will be based base class method.
override for overriding. - means you are invoking your derived class method with the reference of base class. Output will be based on derived class method.
My version of explanation comes from using properties to help understand the differences.
override is simple enough, right ? The underlying type overrides the parent's.
new is perhaps the misleading (for me it was). With properties it's easier to understand:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
Using a debugger you can notice that Foo foo has 2 GetSomething properties, as it actually has 2 versions of the property, Foo's and Bar's, and to know which one to use, c# "picks" the property for the current type.
If you wanted to use the Bar's version, you would have used override or use Foo foo instead.
Bar bar has only 1, as it wants completely new behavior for GetSomething.
Not marking a method with anything means: Bind this method using the object's compile type, not runtime type (static binding).
Marking a method with virtual means: Bind this method using the object's runtime type, not compile time type (dynamic binding).
Marking a base class virtual method with override in derived class means: This is the method to be bound using the object's runtime type (dynamic binding).
Marking a base class virtual method with new in derived class means: This is a new method, that has no relation to the one with the same name in the base class and it should be bound using object's compile time type (static binding).
Not marking a base class virtual method in the derived class means: This method is marked as new (static binding).
Marking a method abstract means: This method is virtual, but I will not declare a body for it and its class is also abstract (dynamic binding).
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
}
I have static variables and methods in a class. Will they be inherited in derived classes or not?
For example:
class A
{
public static int x;
public static void m1()
{
some code
}
}
class B:A
{
B b=new B();
b.m1(); // will it be correct or not, or will I have to write
// new public voim1(); or public void m1();
b.x=20; // will it be correct or not?
}
The static members will be available in the derived class, but you can't access them using an instance reference. Either you access them directly:
m1();
x = 20;
or by using the name of the class:
A.m1();
A.x = 20;
The static members will be available, but you won't be able to reference them on the instance. Instead, reference using the type.
E.g.
class B:A
{
public void Foo()
{
A.m1();
A.x=20;
}
}
Static members are available, but you won't be able to reference them on the instance. Hence you must use the class prefix of the superclass. A.m1().
This is in direct contrast to the Java language where you can access static methods and fields using instance references.
A static member is not associated with an instance because its a Class variable or a Class method, you can access it using the class name. It is usually used to retain general Class information for example number of instances created and etc.
What are differences between declaring a method in a base type "virtual" and then overriding it in a child type using the "override" keyword as opposed to simply using the "new" keyword when declaring the matching method in the child type?
I always find things like this more easily understood with pictures:
Again, taking joseph daigle's code,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
If you then call the code like this:
Foo a = new Bar();
a.DoSomething();
NOTE: The important thing is that our object is actually a Bar, but we are storing it in a variable of type Foo (this is similar to casting it)
Then the result will be as follows, depending on whether you used virtual/override or new when declaring your classes.
The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}
This prints false, if you used override it would have printed true.
(Base code taken from Joseph Daigle)
So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.
Here's some code to understand the difference in the behavior of virtual and non-virtual methods:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
The new keyword actually creates a completely new member that only exists on that specific type.
For instance
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
The method exists on both types. When you use reflection and get the members of type Bar, you will actually find 2 methods called DoSomething() that look exactly the same. By using new you effectively hide the implementation in the base class, so that when classes derive from Bar (in my example) the method call to base.DoSomething() goes to Bar and not Foo.
Beyond just the technical details, I think using virtual/override communicates a lot of semantic information on the design. When you declare a method virtual, you indicate that you expect that implementing classes may want to provide their own, non-default implementations. Omitting this in a base class, likewise, declares the expectation that the default method ought to suffice for all implementing classes. Similarly, one can use abstract declarations to force implementing classes to provide their own implementation. Again, I think this communicates a lot about how the programmer expects the code to be used. If I were writing both the base and implementing classes and found myself using new I'd seriously rethink the decision not to make the method virtual in the parent and declare my intent specifically.
virtual / override tells the compiler that the two methods are related and that in some circumstances when you would think you are calling the first (virtual) method it's actually correct to call the second (overridden) method instead. This is the foundation of polymorphism.
(new SubClass() as BaseClass).VirtualFoo()
Will call the SubClass's overriden VirtualFoo() method.
new tells the compiler that you are adding a method to a derived class with the same name as a method in the base class, but they have no relationship to each other.
(new SubClass() as BaseClass).NewBar()
Will call the BaseClass's NewBar() method, whereas:
(new SubClass()).NewBar()
Will call the SubClass's NewBar() method.
The difference between the override keyword and new keyword is that the former does method overriding and the later does method hiding.
Check out the folllowing links for more information...
MSDN and Other
new keyword is for Hiding. - means you are hiding your method at runtime. Output will be based base class method.
override for overriding. - means you are invoking your derived class method with the reference of base class. Output will be based on derived class method.
My version of explanation comes from using properties to help understand the differences.
override is simple enough, right ? The underlying type overrides the parent's.
new is perhaps the misleading (for me it was). With properties it's easier to understand:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
Using a debugger you can notice that Foo foo has 2 GetSomething properties, as it actually has 2 versions of the property, Foo's and Bar's, and to know which one to use, c# "picks" the property for the current type.
If you wanted to use the Bar's version, you would have used override or use Foo foo instead.
Bar bar has only 1, as it wants completely new behavior for GetSomething.
Not marking a method with anything means: Bind this method using the object's compile type, not runtime type (static binding).
Marking a method with virtual means: Bind this method using the object's runtime type, not compile time type (dynamic binding).
Marking a base class virtual method with override in derived class means: This is the method to be bound using the object's runtime type (dynamic binding).
Marking a base class virtual method with new in derived class means: This is a new method, that has no relation to the one with the same name in the base class and it should be bound using object's compile time type (static binding).
Not marking a base class virtual method in the derived class means: This method is marked as new (static binding).
Marking a method abstract means: This method is virtual, but I will not declare a body for it and its class is also abstract (dynamic binding).
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
}
I have a helper class that is just a bunch of static methods and would like to subclass the helper class. Some behavior is unique depending on the subclass so I would like to call a virtual method from the base class, but since all the methods are static I can't create a plain virtual method (need object reference in order to access virtual method).
Is there any way around this? I guess I could use a singleton.. HelperClass.Instance.HelperMethod() isn't so much worse than HelperClass.HelperMethod(). Brownie points for anyone that can point out some languages that support virtual static methods.
Edit: OK yeah I'm crazy. Google search results had me thinking I wasn't for a bit there.
I don't think you are crazy. You just want to use what is impossible currently in .NET.
Your request for virtual static method would have so much sense if we are talking about generics.
For example my future request for CLR designers is to allow me to write intereface like this:
public interface ISumable<T>
{
static T Add(T left, T right);
}
and use it like this:
public T Aggregate<T>(T left, T right) where T : ISumable<T>
{
return T.Add(left, right);
}
But it's impossible right now, so I'm doing it like this:
public static class Static<T> where T : new()
{
public static T Value = new T();
}
public interface ISumable<T>
{
T Add(T left, T right);
}
public T Aggregate<T>(T left, T right) where T : ISumable<T>, new()
{
return Static<T>.Value.Add(left, right);
}
Virtual static methods don't make sense. If I call HelperClass.HelperMethod();, why would I expect some random subclass' method to be called? The solution really breaks down when you have 2 subclasses of HelperClass - which one would you use?
If you want to have overrideable static-type methods you should probably go with:
A singleton, if you want the same subclass to be used globally.
A tradition class hierarchy, with a factory or dependency injection, if you want different behavior in different parts of your application.
Choose whichever solution makes more sense in your situation.
You can achieve the same effect by just having a regular static method and then shadow it with the new keyword
public class Base
{
//Other stuff
public static void DoSomething()
{
Console.WriteLine("Base");
}
}
public class SomeClass : Base
{
public new static void DoSomething()
{
Console.WriteLine("SomeClass");
}
}
public class SomeOtherClass : Base
{
}
Then you can call the methods like so
Base.DoSomething(); //Base
SomeClass.DoSomething(); //SomeClass
SomeOtherClass.DoSomething(); //Base
Indeed, this can be done in Delphi. An example:
type
TForm1 = class(TForm)
procedure FormShow(Sender: TObject);
end;
TTestClass = class
public
class procedure TestMethod(); virtual;
end;
TTestDerivedClass = class(TTestClass)
public
class procedure TestMethod(); override;
end;
TTestMetaClass = class of TTestClass;
var
Form1: TForm1;
implementation
{$R *.dfm}
class procedure TTestClass.TestMethod();
begin
Application.MessageBox('base', 'Message');
end;
class procedure TTestDerivedClass.TestMethod();
begin
Application.MessageBox('descendant', 'Message');
end;
procedure TForm1.FormShow(Sender: TObject);
var
sample: TTestMetaClass;
begin
sample := TTestClass;
sample.TestMethod;
sample := TTestDerivedClass;
sample.TestMethod;
end;
Quite interesting. I no longer use Delphi, but I recall being able to very easily create different types of controls on a custom designer canvas using the metaclass feature: the control class, eg. TButton, TTextBox etc. was a parameter, and I could call the appropriate constructor using the actual metaclass argument.
Kind of the poor man's factory pattern :)
I come from Delphi and this is a feature among many that I sorely miss in c#. Delphi would allow you to create typed type references and you could pass the type of a derived class wherever the type of a parent class was needed. This treatment of types as objects had powerful utility. In particular allowing run time determination of meta data. I am horribly mixing syntax here but in c# it would look something like:
class Root {
public static virtual string TestMethod() {return "Root"; }
}
TRootClass = class of TRoot; // Here is the typed type declaration
class Derived : Root {
public static overide string TestMethod(){ return "derived"; }
}
class Test {
public static string Run(){
TRootClass rc;
rc = Root;
Test(rc);
rc = Derived();
Test(rc);
}
public static Test(TRootClass AClass){
string str = AClass.TestMethod();
Console.WriteLine(str);
}
}
would produce:
Root
derived
You are not crazy. What you are referring to is called Late Static Binding; it's been recently added to PHP. There's a great thread that describes it - here: When would you need to use late static binding?
a static method exists outside of an instance of a class. It cannot use any non-static data.
a virtual method will be "overwritten" by an overloaded function depending of the type of an instance.
so you have a clear contradiction between static and virtual.
This is not a problem of support, It is a concept.
Update: I was proven wrong here(see comments):
So I doubt you will find any OOP-Language which will support virtual
static methods.
There is a way to force an inheritance of "abstract static" methods from an abstract generic class. See as follow :
public abstract class Mother<T> where T : Mother<T>, new()
{
public abstract void DoSomething();
public static void Do()
{
(new T()).DoSomething();
}
}
public class ChildA : Mother<ChildA>
{
public override void DoSomething() { /* Your Code */ }
}
public class ChildB : Mother<ChildB>
{
public override void DoSomething() { /* Your Code */ }
}
Example (using the previous Mother):
public class ChildA : Mother<ChildA>
{
public override void DoSomething() { Console.WriteLine("42"); }
}
public class ChildB : Mother<ChildB>
{
public override void DoSomething() { Console.WriteLine("12"); }
}
public class Program
{
static void Main()
{
ChildA.Do(); //42
ChildB.Do(); //12
Console.ReadKey();
}
}
It's not that great since you can inherit from only one abstract class and it will ask you to be lenient with your new() implementation.
More, I think it will be costly memory-wise depending on the size of your inherited classes.
In case you have memory issue, you would have to set every properties/variables after your new in a public method which is an awful way to have default values.
I heard that Delphi suports something like this. It seems it does it by making classes object instances of a metaclass.
I've not seen it work, so I'm not sure that it works, or what's the point for that.
P.S. Please correct me if I'm wrong, since it's not my domain.
Because a virtual method uses the defined type of the instantiated object to determine which implementation to execute, (as opposed to the declared type of the reference variable)
... and static, of course, is all about not caring if there's even an instantiated instance of the class at all...
So these are incompatible.
Bottom line, is if you want to change behavior based on which subclass an instance is, then the methods should have been virtual methods on the base class, not static methods.
But, as you already have these static methods, and now need to override them, you can solve your problem by this:
Add virtual instance methods to the base class that simply delegate to the static methods, and then override those virtual instance wrapper methods (not the static ones) in each derived subclass, as appropriate...
It is actually possible to combine virtual and static for a method or a member by using the keyword new instead of virtual.
Here is an example:
class Car
{
public static int TyreCount = 4;
public virtual int GetTyreCount() { return TyreCount; }
}
class Tricar : Car
{
public static new int TyreCount = 3;
public override int GetTyreCount() { return TyreCount; }
}
...
Car[] cc = new Car[] { new Tricar(), new Car() };
int t0 = cc[0].GetTyreCount(); // t0 == 3
int t1 = cc[1].GetTyreCount(); // t1 == 4
Obviously the TyreCount value could have been set in the overridden GetTyreCount method, but this avoids duplicating the value. It is possible to get the value both from the class and the class instance.
Now can someone find a really intelligent usage of that feature?
Mart got it right with the 'new' keyword.
I actually got here because I needed this type of functionality and Mart's solution works fine. In fact I took it one better and made my base class method abstract to force the programmer to supply this field.
My scenario was as follows:
I have a base class HouseDeed. Each House type is derived from HouseDeed must have a price.
Here is the partial base HouseDeed class:
public abstract class HouseDeed : Item
{
public static int m_price = 0;
public abstract int Price { get; }
/* more impl here */
}
Now lets look at two derived house types:
public class FieldStoneHouseDeed : HouseDeed
{
public static new int m_price = 43800;
public override int Price { get { return m_price; } }
/* more impl here */
}
and...
public class SmallTowerDeed : HouseDeed
{
public static new int m_price = 88500;
public override int Price { get { return m_price; } }
/* more impl here */
}
As you can see I can access the price of the house via type SmallTowerDeed.m_price, and the instance new SmallTowerDeed().Price
And being abstract, this mechanism nags the programmer into supplying a price for each new derived house type.
Someone pointed how 'static virtual' and 'virtual' are conceptually at odds with one another. I disagree. In this example, the static methods do not need access to the instance data, and so the requirements that (1) the price be available via the TYPE alone, and that (2) a price be supplied are met.
An override method provides a new implementation of a member that is inherited from a base class. The method that is overridden by an override declaration is known as the overridden base method. The overridden base method must have the same signature as the override method.
You cannot override a non-virtual or static method. The overridden base method must be virtual, abstract, or override.
An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier.
You cannot use the new, static, or virtual modifiers to modify an override method.
An overriding property declaration must specify exactly the same access modifier, type, and name as the inherited property, and the overridden property must be virtual, abstract, or override.
You can use the new keyword
namespace AspDotNetStorefront
{
// This Class is need to override StudioOnlineCommonHelper Methods in a branch
public class StudioOnlineCommonHelper : StudioOnlineCore.StudioOnlineCommonHelper
{
//
public static new void DoBusinessRulesChecks(Page page)
{
StudioOnlineCore.StudioOnlineCommonHelper.DoBusinessRulesChecks(page);
}
}
}
It is possible to simulate the functionality by using the new keyword in the derived class and throwing the NotSupportedException() in the base.
public class BaseClass{
public static string GetString(){
throw new NotSupportedException(); // This is not possible
}
}
public class DerivedClassA : BaseClass {
public static new string GetString(){
return "This is derived class A";
}
}
public class DerivedClassB : BaseClass {
public static new string GetString(){
return "This is derived class B";
}
}
static public void Main(String[] args)
{
Console.WriteLine(DerivedClassA.GetString()); // Prints "This is derived class A"
Console.WriteLine(DerivedClassB.GetString()); // Prints "This is derived class B"
Console.WriteLine(BaseClass.GetString()); // Throws NotSupportedException
}
Due to the fact that it is not possible to detect this condition at compile time and that IntelliSense won't suggest that such function should be implemented in the derived class, this is a potential headache.
One comment also suggested to use NotImplemetedException(). Microsoft's documentation indicates that neither of these exceptions should be handled so any of them should work.
The differences between NotSupportedException and NotImplemetedException are commented in this blog.
You will be able to soon, in C# 11!
From Tutorial: Explore C# 11 feature - static virtual members in interfaces:
C# 11 and .NET 7 include static virtual members in interfaces. This feature enables you to define interfaces that include overloaded operators or other static members.