class Parent
{
public int GetNo()
{
return 1;
}
}
class Child : Parent
{
public Child()
{
}
public int GetNo()
{
return 2;
}
}
Parent p = new Child();
p.GetNo();
But it calls Base.GetNo(). I know if I use virutal in base it will call Child.GetNo()
But i can't use virutal in Base becuase i have to derive my class from base which is already distributed in DLL.So there's no way i can modify the existing functions of base class.
Any sugguestions are valued.
Thanks
You can cast it:
((Child)p).GetNo();
or
if(p is Child)
(p as Child).GetNo();
I have just come here so i could find a solution that doesn't use casts, but since i didn't find it here is one.
Maybe it can be of help for someone.
abstract class Parent
{
public int GetNo()
{
return GetNoImpl();
}
protected abstract int GetNoImpl();
}
class Child : Parent
{
public Child()
{
}
protected override int GetNoImpl();
{
return 2;
}
}
Parent p = new Child();
p.GetNo();
Note: the parent class is abstract.
You can force this with an explicit cast e.g.
((Child)p).GetNo();
Or you can use hiding e.g.
public new int GetNo()
{
return 2;
}
Though I think the latter only gets called if the variable is typed to the class that hides the method.
If you really need to override a method properly and it's from a compiled DLL consider getting in touch with the developers to see whether they can make the method virtual (and if not why) or if an open source project just get the source code and modify it yourself.
Without virtual declared on the method, the base method will always be called because you declared your variable as Parent. If you can't append virtual to the base class, then you can only either declare the variable as Child, or cast it to Child and call your GetNo method:
Child p = new Child();
p.GetNo();
Or:
Parent p = new Child();
((Child)p).GetNo();
Related
public class Parent {}
public class Child: Parent {
public Child() {
Parent instance_of_Parent = INSERTCODEHERE;
}
}
How can I create the desired instance of the parent class in a method of the child class (not necessarily in the constructor, although that's the method I chose for brevity), without referring to "Parent" by name but instead somehow identifying it as the parent of the current class?
If you don't care about performance this will work:
public class Child: Parent {
public Child()
{
var baseClass = GetType().BaseType;
dynamic instance_of_Parent = Activator.CreateInstance(baseClass);
}
}
GetType().BaseType.GetConstructor(new Type[]{}).Invoke(null);
Thank you to DnaJur on the Rimworld Discord for this answer that allows selection of a specific constructor for the parent class to be used for the instantiation.
I am trying to dynamically instantiate classes descendant of an abstract class, but the activator is forcing me to override the constructor to every descendant. Is there a way to avoid this?
P.S: I need to pass the parameters in the constructor, only there it can be Write, otherwise, it will always be read!
Is there a way to avoid this?
Short answer: Yes, when you define no constructor in your derived class, the (abstract) base class constructors are used. When you define one, you have to redefine all constructors.
Not without a workaround pattern.
EDIT: Sorry, I'm wrong that does only work for parameterless constructors.
How you can achive your goal,
is using a protected parameterless constructor and a static Create method:
public abstract class Duck {
private string _DucksParam0;
public string DucksParam0 {
get {
return _DucksParam0;
}
}
// Using protected, this constructor can only be used within the class instance
// or a within a derived class, also in static methods
protected Duck() { }
public static DuckT Create<DuckT>(string param0)
where DuckT : Duck
{
// Use the (implicit) parameterless constructor
DuckT theDuck = (DuckT)Activator.CreateInstance(typeof(DuckT));
// This is now your "real" constructor
theDuck._DucksParam0 = param0;
return theDuck;
}
}
public class Donald : Duck {
}
Usage (dotnetfiddle):
public class Program
{
public void Main()
{
Duck d = Duck.Create<Donald>("Hello World");
Console.WriteLine(d.DucksParam0);
}
}
Constructors are not inherited, so if you must instantiate a child object through a constructor with those parameters, then you need to write a new constructor in the child class that basically does base(p1, p2, ..., pn).
Looking at your code, seems that your constructors only assign/initialize fields, so there is no reason why you can't do that somewhere outside the constructor, as long as you control it appropriately. This might be a long shot, but I feel this is more what you want:
public abstract class Parent
{
protected bool foo
{
get;
private set; // just set the property setter as private
}
protected Parent() {
// protected so all instances are created through createAnotherX
// note that nothing is initialized here!
}
public abstract int Enter(); // To override in child classes
// Option 1: use generics
public static T createAnother1<T>(bool f) where T : Parent, new()
{
T p = new T();
p.foo = f;
return p;
}
// Option 2: use the runtime type
public static Parent createAnother2(Type t, bool f)
{
Parent p = Activator.CreateInstance(t) as Parent;
p.foo = f;
return p;
}
// Examples
public static void Main()
{
Parent p1 = Parent.createAnother1<Child>(true);
Parent p2 = Parent.createAnother2(typeof(Child), true);
}
}
// the child class only has to worry about overriding Enter()
public class Child : Parent
{
public override int Enter()
{
return 1;
}
}
Note that you must instantiate objects through the createAnotherX because the default constructor is protected. In addition, as per your comment, see that the property is defined so that only you can set values, which is what you tried to do in your code when explicitly ignoring the setter.
I'm not sure if this is allowed in C#, but I'm pretty sure I've done it in other languages before.
Let's say I have class, Parent, which has children Child0 and Child1. I make an array of type Parent where Array[0] is of type Child0 and Array[1] is of type Child1. In this scenario, how do I call the children's methods? When I type Array[0].Method(), it calls the Parent version of Method. How do I get it to call the Child0 version of Method? Is this possible?
You just have to declare Method as virtual in the base class:
public class Parent{
public virtual void Method(){
...
}
}
and override it in the heriting classes :
public class Child : Parent{
public override void Method(){
...
}
}
Note that if you don't really need a "standard" implementation in your Parent class, because all the inherithing classes have there own version, you can also set the method as abstract:
public class Parent{
abstract public void Method();
}
Then you don't have the choice and all the classes that inherit from Parent will have to provide an implementation for Method, otherwise you'll have a compile time error.
if you make the parent method virtual you can override the base method in your child classes.
public class Human
{
// Virtual method
public virtual void Say()
{
Console.WriteLine("i am a human");
}
}
public class Male: Human
{
// Override the virtual method
public override void Say()
{
Console.WriteLine("i am a male");
base.Draw(); // --> This will access the Say() method from the
//parent class.
}
}
add them to the array: (altho i would personally use a List<T>)
Human[] x = new Human[2];
x[0] = new Human();
x[1] = new Male();
print out results:
foreach (var i in x)
{
i.Say();
}
will print out
"i am a human" // --> (parent class implementation)
"i am a male" // --> (child class implementation)
Ok, edited the code for clarification:
Question: How can I access the attribute [MyAttr("...")] in TestClassOne/Two from BaseClass.TheAttribute...?
All classes except TestClassOne/Two will be compiled in to my "core" and delivered as a dev-platform to a customer.
The TestClassOne/Two is developed by the customer, so there can be no knowledge of the TestClassOne/Two in the "core".
Code below is compiled into "core" and delivered to customer as dll.
[TestMethod()]
public void AttrTest()
{
var one = new TestClassOne();
var attrOne = one.MyTestProperty.TheAttribute;
var two = new TestClassTwo();
var attrTwo = two.MyTestProperty.TheAttribute;
}
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
}
public class BaseClass
{
public string TheAttribute
{
get {
// Here I would like to get the "[MyAttr("...")]" from the classes in the bottom
return null;
}
}
}
public class SubClass : BaseClass
{
}
Code below is developed by customer (using my dll's)
public class TestClassOne
{
[MyAttr("Attribute one")]
public SubClass MyTestProperty = new SubClass();
}
public class TestClassTwo
{
[MyAttr("Attribute two")]
public SubClass MyTestProperty = new SubClass();
}
You can get directly from type Test:
var result = typeof (Test)
.GetField("MyTest", BindingFlags.Public | BindingFlags.Instance)
.GetCustomAttribute<MyAttr>();
Edit 3:
You can walk the call stack, looking for a relevant attribute in a relevant member in a relevant class. Try this:
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
public string getAttr()
{
return _test;
}
}
public class BaseClass
{
private string theString;
public BaseClass()
{
StackTrace callStack = new StackTrace();
for ( int i = 0; i < callStack.FrameCount; i++ )
{
Type t = callStack.GetFrame(i).GetMethod().DeclaringType;
foreach ( MemberInfo m in t.GetMembers().Where(x => typeof(BaseClass).IsAssignableFrom(x.Type)) )
{
foreach ( var z in m.GetCustomAttributes(typeof(MyAttr)) )
{
MyAttr theAttr = z as MyAttr;
if ( z!= null )
{
theString = z.getAttr();
return;
}
}
}
}
}
public string Test
{
get {
return theString;
}
}
}
This requires that your customer always initializes the SubClass member inside the class that declares it. If they start deriving TestClassOne or have it and TestClassTwo derive from a common class that initializes the member, this code will break.
With clever use of reflection, you can expand the above code to cover more use cases, but that's beyond the scope of this question.
Edit 2:
No. I'm sorry, but what you're trying to do isn't possible. There's no "normal" way for an instance of SubClass to know if it's being declared in a member field of some other object, or in an element in an array or in a temporary variable in the stack, or whatever. As such, there's no way for that instance to access the attributes of the member field that's declaring it.
(I suppose you might want to try to access the garbage collector to find out where in memory the this object lives, but that's probably way beyond the scope of this problem, and in any case, not something I know how to do.)
I suspect your problem lies elsewhere entirely. Maybe you need to require your customer to make TestClassOne and TestClassTwo derive from a common abstract class. Maybe they need to derive from BaseClass themselves. Maybe you need to add parameters to the constructor. Maybe you need to provide a different interface altogether. We can't know unless you provide more information on your specific business requirements.
Edit:
To access the attributes declared on the MyTest member, try something along these lines:
public class BaseClass
{
public string Test
{
get {
var attr = typeof(Test).GetMembers().Where(x => x.Type == this.GetType()).First().GetCustomAttributes(true);
return null;
}
}
}
This will search class Test for a member with the same type as this and look for attributes on that member.
(I don't have my Visual Studio here, to check the exact Where syntax, but it should be pretty close to that...)
Original Answer:
Your attribute is declared on the MyTest member of class Test. But, you're doing GetCustomAttributes on class SubClass itself.
Try this:
[MyAttr("apa")]
public class SubClass : BaseClass
{
}
public class Test
{
public SubClass MyTest = new SubClass();
}
Should get you what you want.
we have the classes:
class A
{
}
class B:A
{
public void metod(){}
}
and
static class C
{
static void met(B clas)
{
A test = clas as B;
// is it any way to get method "metod " from B via test?
}
}
I know that this look like nonsense but the idea is right, I cannot make B object in C class.
Child can access parent through base. For e.g.
base.SomeMethod();
because when inheriting child knows who parent is and that parent class becomes base
but there is no keyword like child because base does not know which class will inherit it.
A child can have a single parent but a parent can have one or more child.
You need to convert it back like this and than you can access
Base derivedInstance = new Derived();
Derived child= (Derived)derivedInstance;
child.Callmethod();
in short
A test = clas as B;
((B)test).method();
You can cast test to B, or simply use the variable declared as B in the first place:
((B)test).metod();
or
clas.metod();
class A
{
public virtual void method(){}
}
class B:A
{
public override void method(){}
}
and
static class C
{
static void met(B clas)
{
A test = clas as B;
test.method(); //this may be what you want?
}
}