I have a base class with a long chain of inheritance. I pass around instances of a child class in a variable with the type of the base class. Can I do a ToString on the instance of the child class and have the child's ToString run (not the parents)?
Here is my attempt:
namespace Abc
{
class A
{
string strA = "A";
public virtual string ToString() { return strA; }
}
class B : A
{
string strB = "B";
public virtual string ToString() { return base.ToString() + strB; }
}
class C : B
{
string strC = "C";
public virtual string ToString() { return base.ToString() + strC; }
}
class Program
{
static void Main(string[] args)
{
A a = new C();
System.Console.WriteLine(a.ToString());
System.Console.ReadLine();
}
}
}
This program outputs A. I thought that adding the virtual keyword would have it output ABC. How can I get this result without casting? Casting requires me to know the type at compile time.
You don't need to declare virtual at each level, you only need to do that in the class that declares it, child classes should do override instead. Because ToString() is defined in Object which is what A is implicitly derived from all off your classes should just use override
class A
{
string strA = "A";
public override string ToString() { return strA; }
//Added a example of somthing not declared in Object
public virtual string Example() { return "I am in A!"; }
}
class B : A
{
string strB = "B";
public override string ToString() { return base.ToString() + strB; }
//Notice the override instead of the virtual.
public override string Example() { return "I am in B!"; }
}
class C : B
{
string strC = "C";
public override string ToString() { return base.ToString() + strC; }
public override string Example() { return "I am in C!"; }
}
What was causing your error is you where Shadowing ToString(), you should have gotten a compiler warning telling you that you where doing that and you needed to use the new keyword to get rid of the compiler warning and explicitly state that you wanted to shadow and not override the method.
Related
If you have a method which is overloaded with a derived type, the method called at run-time depends on the type of your variable, even if the underlying object is actually of the derived type:
class Program
{
static void Main(string[] args)
{
BaseClass theBaseObject = new BaseClass
{
Foo = "FOO"
};
DerivedClass theDerivedObject = new DerivedClass
{
Foo = "FOO",
Bar = "BAR"
};
Processor processor = new Processor();
Console.WriteLine(processor.Compose(theBaseObject));
Console.WriteLine(processor.Compose(theDerivedObject));
Console.WriteLine(processor.Compose((BaseClass) theDerivedObject));
}
}
public class Processor
{
public string Compose(BaseClass item)
{
return item.Foo;
}
public string Compose(DerivedClass item)
{
return Compose((BaseClass)item) + item.Bar;
}
}
public class BaseClass
{
public string Foo { get; set; }
}
public class DerivedClass : BaseClass
{
public string Bar { get; set; }
}
Actual Output:
FOO
FOOBAR
FOO
I would like to find a way to alter this behaviour such that the most specific method invoked for a given parameter.
Desired output:
FOO
FOOBAR
FOOBAR // because theDerivedObject is an instance of DerivedClass
This would allow specific processing for a bunch of items, all derived from a base.
Is this possible in c#?
Edit:
A clarification - in practice there would be no explicit cast, as the items would likely be in a list of collection of mixed types:
Example using a list without an explicit cast:
foreach (BaseClass item in new []{ theBaseObject, theDerivedObject })
{
Console.WriteLine(processor.Compose(item));
}
Actual output:
FOO
FOO
Desired output:
FOO
FOOBAR
Obviously the cast is still happening - but it's not easy to remove it.
This code reminds me of the Haddocks' Eyes poem:
But I was thinking of a plan
To dye one's whiskers green,
And always use so large a fan
That they could not be seen.
First, your code creates a subclass, but then it casts the object back to the base class, so the compiler cannot see the actual type! The overload in your example is resolved at compile time, so the Compose(BaseClass item) will be called.
You could turn things around and have .NET resolve the overload dynamically for you by hiding all overloads, and exposing a single method that takes a base class and performs a dynamic cast:
public class Processor {
public string Compose(BaseClass item) {
return ComposeImpl((dynamic)item);
}
private string ComposeImpl(BaseClass item) {
return item.Foo;
}
private string ComposeImpl(DerivedClass item) {
return ComposeImpl((BaseClass)item) + item.Bar;
}
}
The "magic" is on this line:
return ComposeImpl((dynamic)item);
the item is cast to dynamic, which tells the system that the actual overload of ComposeImpl must be picked based on the run-time type of the BaseClass object.
First of all the reason you are getting the result you are getting the result you are getting is because of you specifically declared theDerivedObject as DerivedClass therefor it will go DerivedClass as parameter and with (BaseClass) theDerivedObject) you bassically just told the compiler (correct me if im wrong with compiler) or program to take the method with the parameter BaseClass
What you want to do is one of the following options
Number 1:
public class Processor
{
public string Compose(BaseClass item)
{
if (item is DerivedClass)
return Compose((DerivedClass) item);
return item.Foo;
}
public string Compose(DerivedClass item)
{
return item.Foo + item.Bar;
}
}
Number 2
public class Processor
{
public string Compose(BaseClass item)
{
if (item is DerivedClass)
{
var derived = (DerivedClass) item;
return derived.Foo + derived.Bar;
}
return item.Foo;
}
}
Or you might want to overide ToString()
public class Processor
{
public string Compose(BaseClass item)
{
var #class = item as DerivedClass;
return #class?.ToString() ?? item.ToString();
}
}
public class BaseClass
{
public string Foo { get; set; }
public override string ToString()
{
return Foo;
}
}
public class DerivedClass : BaseClass
{
public string Bar { get; set; }
public override string ToString()
{
return Foo + Bar;
}
}
If you are not using C#6.0 then Processor will be the following
public class Processor
{
public string Compose(BaseClass item)
{
var #class = item as DerivedClass;
if (#class != null)
{
return #class.ToString();
}
return item.ToString();
}
}
public class Processor
{
public string Compose(BaseClass item)
{
return item.Compose();
}
}
public class BaseClass
{
public string Foo { get; set; }
public virtual string Compose()
{
return Foo;
}
}
public class DerivedClass : BaseClass
{
public string Bar { get; set; }
public override string Compose()
{
return base.Compose() + Bar;
}
}
No wonder you are getting what you get. You overload Compose method. You declare two signatures one for base class, another for derived. Then you call the method several times:
processor.Compose(theBaseObject) calls Compose(BaseClass item)
processor.Compose(theDerivedObject) calls Compose(DerivedClass item). It happens here that several methods might be suitable for the call. Compiler selects a method having closest base class in the hierarchy which is itself DerivedClass.
processor.Compose((BaseClass) theDerivedObject)) calls Compose(BaseClass item) because you've told him to do it. It has no options to chose from.
You've might be interrested in class virtual member overriding. See
public class BaseClass
{
public string Foo { get; set; }
public virtual string GetComposeResult() { return Foo; }
}
public class DerivedClass : BaseClass
{
public string Bar { get; set; }
public override string GetComposeResult() { return Foo + Bar; }
}
In this case using following code would do what you expect.
public class Processor
{
public string Compose(BaseClass item) { return item.GetComposeResult(); }
}
I'm learning OOAD and trying to implement class relationship with inheritance but there is an issue here is the code
Parent Class
namespace ConsoleApplication1
{
abstract class Classification
{
public abstract string type();
}
}
1st Child Class
namespace ConsoleApplication1
{
class FullTime : Classification
{
bool inCampus;
string roomDetail;
float rent;
public FullTime(string studentRoomDetail, float studentRent)
{
this.inCampus = true;
this.roomDetail = studentRoomDetail;
this.rent = studentRent;
}
public FullTime()
{
this.inCampus = false;
}
public string printAccommodationDescription()
{
if (!this.inCampus)
{
return "Not in campus";
}
else
{
return "Room: " + this.roomDetail + " Rent: " + this.rent.ToString();
}
}
public override string type()
{
return "fulltime";
}
}
}
2nd Child Class
namespace ConsoleApplication1
{
class PartTime : Classification
{
bool onJob;
string jobTitle;
float salary;
public PartTime(string studentJobTitle, float studentSalary)
{
this.onJob = true;
this.jobTitle = studentJobTitle;
this.salary = studentSalary;
}
public PartTime()
{
this.onJob = false;
}
public string printJobDescription()
{
if (!this.onJob)
{
return "Not on job";
}
else
{
return "JobTitle: " + this.jobTitle + " Salary: " + this.salary.ToString();
}
}
public override string type()
{
return "parttime";
}
}
}
Now in Program.cs when I tried to access method printJobDescription from PartTime class
Classification classification = new PartTime("Software Engineer", 10000);
classification.printJobDescription();
it says
Error CS1061 'Classification' does not contain a definition for 'printAccommodationDescription' and no extension method 'printAccommodationDescription' accepting a first argument of type 'Classification' could be found (are you missing a using directive or an assembly reference?)
How can I solve this issue?
UPDATE
I need the ability to let object change its class at runtime, so I have to create the object of type Classification and use either method that is not implemented in other class
You can only use the functions declared in the class you use.
abstract class Classification
{
public abstract string type();
}
class PartTime : Classification
{
public override string type() {...}
public Job1() {...}
}
class FullTime : Classification
{
public override string type() {...}
public Job2() {...}
}
A object of type Classification can only use the type()
A object of the type PartTime can use type and Job1()
A object of the type FullTime can use type and Job2()
If you have an object like this:
Classification classification = new PartTime();
and you don´t know which special type, you have to cast this object to use other methods:
if (classification is PartTime)
{
((PartTime)classification).Job1();
}
else if (classification is FullTime)
{
((FullTime)classification).Job2();
}
Hope this helps.
When casting you're object into another object type, that called Polymorphism. This translate that you can only use the methods and properties that exposed to the destination object type, which is Classification which doesn't know your method.
Simple example i made:
using System;
namespace Program
{
public class Program
{
public static void Main()
{
Dog rex = new Dog();
Animal rexAsAnimal = rex;
// Can access 'MakeSound' due the fact it declared at Dog (Inherited by Animal)
Console.WriteLine(rex.MakeSound()); // Output: Bark
// Compilation error: rexAsAnimal is defined as 'Animal' which doesn't have the 'Bark' method.
//Console.WriteLine(rexAsAnimal.Bark()); // Output when uncomment: Compilation error.
// Explicitly telling the compiler to cast the object into "Dog"
Console.WriteLine(((Dog)rexAsAnimal).Bark()); // Output: Bark
}
}
public abstract class Animal
{
public abstract string MakeSound();
}
public class Dog : Animal
{
public override string MakeSound() { return Bark(); }
public string Bark()
{
return "Bark";
}
}
}
Imagine you have a class hierarchy as:
class Base
{
public virtual string GetName()
{
return "BaseName";
}
}
class Derived1 : Base
{
public override string GetName()
{
return "Derived1";
}
}
class Derived2 : Base
{
public override string GetName()
{
return "Derived2";
}
}
In most appropriate way, how can I write the code in a way that all "GetName" methods adds "XX" string to return value in derived class?
For example:
Derived1.GetName returns "Derived1XX"
Derived2.GetName returns "Derived2XX"
Changing the code of GetName method implementation is not good idea, because there may exist several derived types of Base.
Leave GetName non-virtual, and put the "append XX" logic in that function. Extract the name (without "XX") to a protected virtual function, and override that in the child classes.
class Base
{
public string GetName()
{
return GetNameInternal() + "XX";
}
protected virtual string GetNameInternal()
{
return "BaseName";
}
}
class Derived1 : Base
{
protected override string GetNameInternal()
{
return "Derived1";
}
}
class Derived2 : Base
{
protected override string GetNameInternal()
{
return "Derived2";
}
}
This is a good use case for the decorator pattern. Create a decorator that has a reference to a Base:
class BaseDecorator : Base
{
Base _baseType;
public BaseDecorator(Base baseType)
{
_baseType = baseType;
{
public override string GetName()
{
return _baseType.GetName() + "XX";
}
}
Construct a BaseDecorator with your chosen class (Base or Derived), and call GetName on that.
If you don't want to (or can't) modify original classes, you can use extension method:
static class Exts {
public static string GetNameXX (this Base #this) {
return #this.GetName() + "XX";
}
}
You'll be able to access new method as usual:
new Derived1().GetNameXX();
You could split the construction of the name into various overridable parts and then override each part in each of the different subclasses.
Below is one such example.
public class Base {
public string GetName() {
return GetPrefix() + GetSuffix();
}
protected virtual string GetPrefix() {
return "Base";
}
protected virtual string GetSuffix() {
return "";
}
}
public class DerivedConstantSuffix : Base {
protected override string GetSuffix() {
return "XX";
}
}
public class Derived1 : DerivedConstantSuffix {
protected override string GetPrefix() {
return "Derived1";
}
}
public class Derived2 : DerivedConstantSuffix {
protected override string GetPrefix() {
return "Derived2";
}
}
An override can call it's base function... you could then modify the base class to append the characters you want there.
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.