Possible to override static member in base class?

G

Guest

It looks like the language is trying to prevent me from doing this sort of
thing. Nevertheless, the following compiles, and I'd like to know why it
doesn't work the way it should:

public class ComponentA
{
static string s_name = "I am the root class.";
public string Name { get {return s_name;} }
}

public class ComponentB : ComponentA
{
new static string s_name = "I am a derived class.";
}

static void Main()
{
ComponentB b = new ComponentB();
Console.WriteLine("ComponentB says: " + b.Name);
}

I want this to say "I am a derived class." but it still says "I am the root
class."

My objective is to derive a whole bunch of classes on which I can get a
description both
- Through reflection of the class Type (thus requiring the static member)
- Through an instance of the class using a (virtual) member that is defined
in the root class.

Is this possible?
 
M

Mattias Sjögren

My objective is to derive a whole bunch of classes on which I can get a
description both
- Through reflection of the class Type (thus requiring the static member)
- Through an instance of the class using a (virtual) member that is defined
in the root class.

Is this possible?

Why don't you make the Name property virtual and override it in the
derived classes.


Mattias
 
J

Jeffrey Tan[MSFT]

Hi dbooksta,

Thanks for your post!

Yes, C# does not support static virtual member. This is because: to
implement a virtual member, the complier has to place this member as an
entry in the v-table, which attaches to a class instance. Static member
does not attach to any class instance but attaches to the class itself, so
static member can not be virtual and overrided in child class.

You'd better take Mattias' suggestion to mark "Name" instance property as a
virtual one and override it in inherited class. The code snippet below
demonstrates this:

public class ComponentA
{
static string s_name = "I am the root class.";
public virtual string Name { get {return s_name;} }
}

public class ComponentB : ComponentA
{
new static string s_name = "I am a derived class.";
public override string Name { get {return s_name;} }
}

private void button1_Click(object sender, System.EventArgs e)
{
ComponentB b = new ComponentB();
Console.WriteLine("ComponentB says: " + b.Name);
}
Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

OK, this will work. But just to confirm: Is there no way to define an
interface, abstract, or base class such that it REQUIRES that a particular
static member (say "s_name") be defined or redefined in a derived class?

If so, it seems like a language shortcoming, doesn't it?
 
J

Jeffrey Tan[MSFT]

Hi dbooksta,

Thanks for your feedback!

No, you can redefine the static member in the child class with "new"
keyword in C#. This will hide the parent class's static member in the child
class. Since C# does not allow us to use class reference to refer the
static member. The correct way of using the redefined static member is
using the child class name. Please see the sample code snippet below:
private void Form1_Load(object sender, System.EventArgs e)
{
ComponentB b = new ComponentB();
MessageBox.Show("ComponentB says: " + ComponentB.s_name);//you can not use
b.s_name to access the redefined static member, C# compiler prohibits this
way.
}

public class ComponentA
{
public static string s_name = "I am the root class.";
public string Name { get {return s_name;} }
}

public class ComponentB : ComponentA
{
public new static string s_name = "I am a derived class.";
}

Does this meet your need?

Note: your original sample code result is expected. You did not override
Name property in the child class, then when you are using b.Name to access
"Name" property, you are referring the parent class's "Name" property,
which returns parent class's s_name static member to you. In this scenario,
there is no Polymorphism at all.

Below is some more comment on OOP Polymorphism with static member:

In Object Oriented Programming area, static member is a property of the
class itself, it has nothing to do with any instance of that class.
Polymorphism in OOP means initializing a child class instance and assigning
it to the parent class pointer/reference, like this:
ParentClass obj=new ChildClass();

Then we can override the parent class member behavior in the child class.
This is called Polymorphism in OOP. As we can see, in Polymorphism of OOP,
this concept only applies to the class member, which requires initializing
an instance of the class. This concept does not apply to the class itself.
So Polymorphism concept has nothing to do with static member. Also, neither
C++ nor C# support virtual static member.(Because it does not make sense
based on OOP concept)

Hope this information helps!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi dbooksta,

Does my reply make sense to you? If you still have any concern or
questions, please feel free to tell me, thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

FYI to all, I also realized that I could accomplish my objective here by
tagging my classes with an Inheritable Attribute.
 
M

Mark Wilden

Why do Microsoft employees write messages like this? I mean, they respond to
perhaps 1/1000th of the messages posted here, lard those responses with
useless boilerplate, then write equally useless "followups" like this. It's
like they think newsgroups are email support (except that they ignore most
requests).

Sorry - just had to vent.

///ark
 
J

Jeffrey Tan[MSFT]

Hi dbooksta,

Thanks for your feedback!

Can you be specific regarding your finding? Please forgive my ignorance,
based on my research, I can not find any "Inheritable Attribute" in C#
language specification. Can you share your sample code with us? Thanks :)

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Basically I define an Attribute like this:

[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public class ComponentTypeAttribute : Attribute
{
public string ComponentType;
public ComponentTypeAttribute(string c)
{
ComponentType = c;
}
}

Now the root class gets:

[ComponentTypeAttribute("BaseType")]
public class BaseComponent
{
public string ComponentType { get { return
((ComponentTypeAttribute)Attribute.GetCustomAttribute(this.GetType(),
typeof(ComponentTypeAttribute))).ComponentType; } }
}

A little verbose, but the net effect is that a call to .ComponentType member
of ANY derived class will return "BaseType," unless they redefine the
attribute like this:

[ComponentTypeAttribute("SpecialType")]
public class Special : BaseComponent {...}

So when we call Special.Type we get "SpecialType"!

Also, we don't have to instantiate any of these classes to find out what
their ComponentType, because the Attribute is defined on the Type.

Hence, we have the effect of a static property that can be both inherited
and overridden!
 
J

Jeffrey Tan[MSFT]

Hi Dave,

Thanks for your feedback and sharing!
we call Special.Type we get "SpecialType"!
I suspect there is a typo here, do you mean "Special.ComponentType".
we have the effect of a static property that can be both inherited
and overridden
Please forgive my ignorance, which "static property" you are referring to?
I did not find a static property in your reply. Do you mean
"ComponentType"? However, I found this property's "get" accessor will use
"this" keyword, so I assume it is not a static property.

I will wait for your further clarify :)

Additionally, does my original reply of sample code snippet meet your need?

private void Form1_Load(object sender, System.EventArgs e)
{
ComponentB b = new ComponentB();
MessageBox.Show("ComponentB says: " + ComponentB.s_name);//you can not use
b.s_name to access the redefined static member, C# compiler prohibits this
way.
}

public class ComponentA
{
public static string s_name = "I am the root class.";
public string Name { get {return s_name;} }
}

public class ComponentB : ComponentA
{
public new static string s_name = "I am a derived class.";
}
By using "new" keyword, the ComponentB.s_name is overrided per your
request. If this does not meet your need, please feel free to tell me your
concern. Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Your original sample didn't meet my need because if you didn't explicitly
define a "new static string" in the derived class then it wouldn't have a
static member at all. I.e., if we have

public class ComponentA
{
public static string s_name = "I am the root class.";
public virtual string Name { get {return s_name;} }
}

public class ComponentB : ComponentA
{
public new static string s_name = "I am a derived class.";
public override string Name { get {return s_name;} }
}

public class ComponentC : ComponentA { }

You can call ComponentB.s_name, but you can't call ComponentC.s_name.

My sample gives the effect of an inherited static member, because if you
don't define it in the derived class it inherits the value from its parent.

Also you can access the value with either an instance object OR the type
itself. Referencing my earlier code: To access the ComponentTypeAttribute of
a derived class "Special" you could do:

ComponentTypeAttribute attr =
(ComponentTypeAttribute)Attribute.GetCustomAttribute(Special,
typeof(ComponentTypeAttribute));

In this case there is no reference to an instance of Special. But if you
have an instance "s" you can get the attribute by just calling s.GetType() in
place of "Special".
 
J

Jeffrey Tan[MSFT]

Hi Dave,

Cool, Thanks for your clarify! Your logic appears much clearer to me now!

It seems that you are using ComponentTypeAttribute as the static member of
the class, and in inherited class, you can override its original definition
by marking the class with a new ComponentTypeAttribute. Also, you are using
Attribute.GetCustomAttribute to access any class's ComponentTypeAttribute
definition.(inherited from parent class or overrided by this class). Then
ComponentTypeAttribute acts as the static member with overridable and
inheritable feature.
This is really an interesting idea and I think it should work. Thank you
for sharing it with the community. :)
You can call ComponentB.s_name, but you can't call ComponentC.s_name.
Are you sure about this? I have used the following sample code snippet for
testing and I can access ComponentC.s_name without any problem and it
outputs "I am a derived class." which is overrided in ComponentB. It seems
this will achieve the same effect as ComponentTypeAttribute way?

static void Main(string[] args)
{
Console.WriteLine(ComponentC.s_name);
Console.ReadLine();
}

public class ComponentA
{
public static string s_name = "I am the root class.";
public virtual string Name { get {return s_name;} }
}

public class ComponentB : ComponentA
{
public new static string s_name = "I am a derived class.";
public override string Name { get {return s_name;} }
}

public class ComponentC: ComponentB
{
}
If there is any misunderstand in my reply, please feel free to point out.
Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Yes, you are right there, that static member is available in derived classes.

The distinction I was originally trying to make (and I forgot in that last
post) is that the "new static" member doesn't OVERRIDE the base static
member. I was trying to get true static overriding, i.e.:

1. Define a static value in the base class (e.g., s_name = "Base Class")
2. Define a property in the base class that accesses that static value
(e.g., string Name { get { return s_name;}})
3. Be able to optionally override that static value in derived classes in
such a way that the base class's property will then return the derived
class's static value -- without having to redefine the base property.
4. And of course have every derived type return the overridden static value.

If you rely on static s_name members then, even if you "new" the s_name in
the derived class, but you don't override the Name property in the derived
class then the derived class .Name will return the static value of the base
class.

Unfortunately this is a very simple requirement that is very wordy to
describe. Hopefully the following examples will illuminate the difference:

If we do:

public class ComponentA
{
public static string s_name = "I am the root class.";
public virtual string Name { get { return s_name; } }
}

public class ComponentB : ComponentA
{
public new static string s_name = "I am a derived class.";
}

Then ComponentB.s_name => "I am a derived class"
But ComponentB B_instance.Name => "I am the root class"

In contrast, if we use my previously defined attribute and do:

[ComponentTypeAttribute("I am the root class")]
public class ComponentA
{
public string Name { get { return
((ComponentTypeAttribute)Attribute.GetCustomAttribute(this.GetType(),
typeof(ComponentTypeAttribute))).ComponentType; } }
}

[ComponentTypeAttribute("I am a derived class")]
public class ComponentB : ComponentA { }

Then both the static (type) value
(ComponentTypeAttribute)Attribute.GetCustomAttribute(ComponentB,
typeof(ComponentTypeAttribute)) => "I am a derived class"
And ComponentB B_instance.Name => "I am a derived class"

This may look more complicated than overriding the Name property for every
case, but in my current application I have dozens of derived classes and this
particular feature has proven more clear and concise.
 
J

Jeffrey Tan[MSFT]

Hi Dave,

Yes, this makes sense. I can see your real concern and the distinction now
:).

Since you are requiring this feature, your implementation of using
ComponentTypeAttribute should be a valid solution.

The reason the original solution does not work is that Name property is
returning the static field *staticly*, while your implementation returns
the ComponentTypeAttribute with dynamic query. Below is some improvement to
the original solution, if you are curious:

To get what you want with the original solution, we can also dynamically
query the current object instance static field with Reflection. The idea
is: in ComponentB B_instance.Name, we can first get instance type
"ComponentB", then we can use Reflection to query "s_name" field value. The
working sample code snippet is listed below:

static void Main(string[] args)
{
ComponentA obja=new ComponentA();
ComponentB objb=new ComponentB();
ComponentC objc=new ComponentC();

Console.WriteLine(obja.Name);
Console.WriteLine(objb.Name);
Console.WriteLine(objc.Name);
Console.ReadLine();
}

public class ComponentA
{
public static string s_name = "I am the root class.";
public virtual string Name
{
get
{
FieldInfo fi=null;
Type type=this.GetType();
while(fi==null)
{
fi=type.GetField("s_name",
BindingFlags.Static|System.Reflection.BindingFlags.Public );
type=type.BaseType;
}
return
fi.GetValue(null).ToString();
}
}
}

public class ComponentB : ComponentA
{
public new static string s_name = "I am a derived class.";
}

public class ComponentC: ComponentB
{
}

Note: since we did not override "s_name" in ComponentC class,
type.GetField("s_name", ...) will return null in ComponentC instance. So I
use type.BaseType to query base class's "s_name" static field value instead.

This solution uses the same idea as your implementation(getting the static
member value with dynamic binding, which has the same effect as OOP
polymorphism), but since I have to use a while loop in the implemenation, I
think your solution is more elegant. :) Anyway, post here for your
reference.

Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top