Lets suppose we have these classes:
class A {
public string attr = "Class A";
public static void getAttribute(){
self currentClass = new self(); // equivalent to php
Console.Write("Attribute : " + currentClass.attr);
}
}
Class B : A {
public string attr = "Class B";
}
B = new B();
B.getAttribute();
I want B.getAttribute(); to print Attribute: Class B. How can I do this?
This is fundamentally impossible.
B.getAttribute() compiles to A.getAttribute().
I probably know what you are trying to do, but I have to tell you that this kind of PHP approach makes no sense in C#. I discourage you from using it.
public class A
{
private String attr = "Class A";
public static String getAttribute()
{
return (new A()).attr;
}
}
public class B : A
{
private String attr = "Class B";
public static String getAttribute()
{
return (new B()).attr;
}
}
You get the current class instance by the 'this' keyword. Obviously you cannot access that in a static method since by definition a static method executes without the context of a particular instance.
On the other hand, to access a member variable/property/method from inside the same class, you don't need the 'this' keyword at all, since it's implicit.
If you're asking how to do something like that in C#, I think the answer would be along these lines:
public class A
{
public virtual string attr
{
get { return "Class A" }
}
public void getAttribute(){
Console.Write("Attribute : " + attr);
}
}
public class B : A
{
public override string attr
{
get { return "Class B"; }
}
}
var b = new B();
b.getAttribute();
Regarding my comment in the other answer, if you needed getAttribute to be static, you could implement it this way:
public static void getAttribute(A obj){
Console.Write("Attribute : " + obj.attr);
}
You would then call it like this:
var b = new B();
A.getAttribute(b);
Related
Lets say I have three classes, p, p1 and p2
public class p
{
public p() {}
}
public class p_1 : p
{
public p_1() {}
public string tester = "ABC";
}
public class p_2 : p
{
public p_2() {}
public string foo = "Test";
}
Now I want to create a general variable of the type p and then use it as type p_1. Then I want to access the variable tester inside.
p p_tester;
p_tester = new p_1();
Console.Writeline(p_1.tester);
My question is: Why can't I access the .tester variable? Am I missing something? Visual studio wants me to declare all variables from the subclasses in the main class... but that is not what I want.
Is that what I try to do even possible?
The only way I've found to do this is to cast p_tester as p_1.
The one thing I'm sure is that you can't access p_1 directly because your class is not static. You can only access the declared instance p_tester
p p_tester;
p_tester = new p_1();
Console.WriteLine(((p_1)p_tester).tester);
Your declare function is wrong. Why not access it through the child class?
p_1 p_tester;
p_tester = new p_1();
Console.WriteLine(p_tester.tester);
If you want to access the tester form child class p_1() then you could set the tester as static variable.
public class p_1 : p
{
public p_1() {}
public static string tester = "ABC";
}
Console.WriteLine(p_1.tester);
It seems you actually need an override property
public class p
{
public p() {}
public virtual string StringValue { get; }
}
public class p_1 : p
{
public p_1() {}
public string tester = "ABC";
public override string StringValue => tester;
}
public class p_2 : p
{
public p_2() {}
public string foo = "Test";
public override string StringValue => foo;
}
You can now access it using p_tester.StringValue
p p_tester = new p_1();
Console.Writeline(p_1.StringValue);
Code to demonstrate the problem:
static void Main(string[] args)
{
var a = new A();
var b = new B();
Base<>[] all = new Base<>[] { a, b }; // doesn't work
}
class Base<T>
{
public string Caption { get { return typeof(T).ToString(); } }
}
class A : Base<A> { }
class B : Base<B> { }
Perhaps I went the wrong direction. Idea was to move Caption into base class (Base become generic). Non-generic version works without problems:
var all = new Base[] { a, b }; // no problems for as long as Base is not generic
There's no Type<?> in C# - you always have to specify a concrete generic type.
The only way around this is to make Base<T> inherit a non-generic base-class, or implement a non-generic interface. You could then use that as the type of the array.
EDIT:
In your case this is extremely simple, since the part of the interface you want doesn't include the generic type argument. So you can simply do either:
public abstract class Superbase
{
public abstract string Caption { get; }
}
public class Base<T>: Superbase
{
public override string Caption { get { return typeof(T).Name; } }
}
Or, using an interface:
public interface IBase
{
string Caption { get; }
}
public class Base<T>: IBase
{
public string Caption { get { return typeof(T).Name; } }
}
Your array would then be Superbase[] or IBase[], respectivelly. In both cases, you can see that I'm not actually providing an implementation - both the declarations are "abstract", in a sense.
In general, I'm trying to keep the non-generic stuff in a non-generic base class, rather than stuffing it in the derived generic classes. It just feels more clean :)
based on #Luaan ideea, here is an implementation:
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
var arr = new Base[] { a, b};
foreach (var obj in arr)
Console.WriteLine(obj.Caption);
Console.ReadKey();
}
}
public class Base<T> : Base
{
public override string Caption
{
get { return typeof (T).ToString(); }
}
}
public class A : Base<A> { }
public class B : Base<B> { }
public abstract class Base
{
public abstract string Caption { get; }
}
Instead of trying to use inheritance (which will lead to more problems down the line), use an extension method instead:
public interface IClassAORClassB {}
class A : IClassAORClassB { }
class B : IClassAORClassB { }
public static class Captions
{
public static string Caption<T>(this T obj) where T : IClassAORClassB
{
return obj.GetType().ToString();
}
}
static void Main(string[] args)
{
var a = new A();
var b = new B();
var all = new IClassAORClassB[] { a, b }; // works just fine
Console.WriteLine(all[0].Caption()); // prints A
Console.WriteLine(all[1].Caption()); // prints B
}
An interviewer asked me the question below
public class A
{
public string GetName()
{
return "A";
}
}
public class B : A
{
public string GetName()
{
return "B";
}
}
public class C : B()
{
public string GetName
{
return "C";
}
}
What are the outputs of
A a = new A();
a.GetName();
a = new B();
a.GetName();
a = new C();
a.GetName();
I said all will give "A". Then he said i need to correct my basics.
Your answer is correct; there is no method overriding applied due to the absence of virtual and override keywords.
So in all three cases it returns output A.
If you want to apply proper method overriding, you need to apply virtual to the base class methods and override to the child class methods where you are overriding base class method.
Try This:
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.WriteLine(a.GetName());
a = new B();
Console.WriteLine(a.GetName());
a = new C();
Console.WriteLine(a.GetName());
}
}
public class A
{
public virtual string GetName()
{
return "A";
}
}
public class B : A
{
public override string GetName()
{
return "B";
}
}
public class C : B
{
public override string GetName()
{
return "C";
}
}
OUTPUT:
A
B
C
You are assigning all objects (new A(), new B(), new C()) to the variable A a. Since they are all being viewed as type A and the method is not virtual, then the implementation for type A is invoked and "A" is returned.
This link provides a more detailed explanation with samples.
public class B : A
{
public string GetName()
{
return "B";
}
}
is same as
public class B : A
{
public new string GetName()
{
return "B";
}
}
which will hide the method by calling the interface or baseclass,
var b = new B();
b.GetName() ==> "B"
while
A a = new B();
a.GetName() ===> "A"
this is dangrous and I saw lots of people write such code without knowing what's the difference between new and override
I got an abstract base class
public class Base
{
public abstract String Info { get; }
}
and some children.
public class A : Base
{
public override String Info { get { return "A does ..."; } }
}
public class B : Base
{
public override String Info { get { return "B does ..."; } }
}
This is mere a constant but I want to make sure using Base that all classes implement it.
Now I sometimes do not have an object instance but want to access A.Info - this is not possible due it is a instance property.
Is there another way than implementing the same property on instance AND on static level? That would be feel like a duplicate violating DRY programming style.
NEW EDIT: I now see this two solutions:
public class Base
{
public abstract String ClassInfo { get; }
}
public class A : Base
{
public override String ClassInfo { get { return Info; } }
public static String Info { get { return "A does ..."; } }
}
public class B : Base
{
public override String ClassInfo { get { return Info; } }
public static String Info { get { return "In B we do ..."; } }
}
With this I can do with any object of type Base something like object.ClassInfo but also use the value in my factory hardcoded like if(A.Info) return new A(). But I have to implement two properties for the same information in every class.
On the other hand:
public class Base
{
public abstract String ClassInfo { get; }
public static String GetClassInfo<T>() where T : BaseControl, new()
{
T obj = new T();
return obj.ClassInfo;
}
}
public class A : Base
{
public override String ClassInfo { get { return "text A"; } }
}
public class B : Base
{
public override String ClassInfo { get { return "text B"; } }
}
Due to the abstract Base it is made sure that ClassInfo is always implemented. Calls with obj.ClassInfo and Base.GetClassInfo<A>() are okay. But with this every child of Base must have a default constructor without arguments and we loose performance with the unneccessary created instance.
Is there any other idea? Which one would you prefer and why?
If you need specific return results of your static properties, you're better of either
a) Instance properties
2) Attributes
In the example you've already given, you've got an instance of Base, which means you can just make the instance property virtual:
public class Base
{
public virtual string Info { get { return "From Base"; } }
}
public class A : Base
{
public override string Info { get { return "From A"; } }
}
If you wanted to go the attribute route, you define it as such:
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public class InfoAttribute : Attribute
{
public InfoAttribute(string info) { this.Info = info; }
public string Info { get; private set; }
}
[InfoAttribute(Info = "From Base")]
public class Base
{
public string GetInfo()
{
var attr = GetType()
.GetCustomAttributes(typeof(InfoAttribute), true)
.FirstOrDefault();
return (attr == null) ? null : attr.Info;
}
}
[InfoAttribute(Info = "From A")]
public class A : Base { }
If you wanted to call it as a static function call, you could make this change:
public static string GetInfo(Base instance)
{
var attr = instance.GetType()
.GetCustomAttributes(typeof(InfoAttribute), true)
.FirstOrDefault();
return (attr == null) ? null : attr.Info;
}
And then call it as: Base.GetInfo(instance);. All in all, not very elegant!
This is not possible.
static members cannot be virtual or abstract.
You should make an abstract instance property.
Statics can't be overridden. If you truly want to do something like that, you'd want an instance property that is virtual in the base that gets overridden in the subclasses.
Does it compiled? I don't think so. Static cannot be marked as override, virtual or abstract.
ok this may sound a little crazy but, i have class A and a function, returns an instance of A, also called A() and i have to access a static field of class A.
public class A
{
public static int Num = 1;
}
class Program
{
public A A()
{
Console.WriteLine(A.Num); // Error points here. A.Num.
return new A();
}
}
and i get
'Program.A()' is a 'method', which is
not valid in the given context
what is the solution?
thanks.
Well, you can specify the namespace:
Console.WriteLine(Foo.Bar.A.Num);
If there's no namespace, use the global namespace alias:
Console.WriteLine(global::A.Num);
use the namesapce instead
namesapce test {
public class A
{
public static int Num = 1;
}
class Programs:A
{
public A A()
{
Console.WriteLine(test.A.Num);
return new A();
}
}
}