I have a class hierarchy (In .Net 3.5) as shown:
Parent
- Child1
- Child2
- Child3
I have a base class as shown:
public abstract class BaseClass
{
protected Parent field;
public BaseClass(Parent someField)
{
this.field = someField
}
public string Property1
{
get { return field.Child1Property; }
set { field.Child1Property = value; }
}
}
The parameter that I'm passing in the constructor is going to be one of the Children. Is there a way to access the Child properties through a variable of the Parent type?
Alternately, is it possible to do this:
public abstract class BaseClass
{
protected Parent field;
protected Type childType; //Type? Or something else?
public BaseClass(Parent someField)
{
//assign the runtime type of someField to childType
this.field = someField
}
public string Property1
{
get { return ((childType)field).Child1Property; } //Is this possible?
set { ((childType)field).Child1Property = value; }
}
}
If I use Type it doesn't seem to work since ((childType)field).Child1Property is not allowed. The problem is, I only find out what type of child is being passed at runtime so casting the field to the appropriate type doesn't seem to be possible.
Help!
You can do this:
public abstract class BaseClass
{
protected Parent field;
public BaseClass(Parent someField)
{
this.field = someField
if (someField is Child1)
this.Property1 = ((Child1)someField).Foo();
}
public Int32 Property1
{
get { return field.Child1Property; }
set { field.Child1Property = value; }
}
}
However, there is a caveat here. You need to know that the instance of parent being passed in is of type Child1, or nothing will happen. Generally it's considered a bad design to have an if/then that covers every possible child class, because that means that when you add another child in the future, you'll need to remember to come back here and add it to the if/then.
The proper way to do this is really to have a property in Parent that is overriden in child:
public class Parent {
public virtual Int32 Foo() { return 5; }
}
public class Child1 : Parent {
public override Int32 Foo() { return 7; }
}
And then use that property:
public BaseClass(Parent someField)
{
this.field = someField
// If someField happens to be a Child1, this will be 7
this.Property1 = someField.Foo();
}
Looks like you propably want to use an Interface or generics.
Related
I have three classes, two of which inherit from a base class, and the third which I would like to reference one of the other two depending on the state of the application.
public class Batch
{
public Batch() { }
}
public class RequestBatch : Batch
{
public RequestBatch(string batchJobType) : base(batchJobType) { }
public override int RecordCount
{
get { return Lines.Count; }
}
}
public class ResponseBatch : Batch
{
public ResponseBatch(string batchJobType) : base(batchJobType) { }
public ResponseBatch(int BatchJobRunID)
{ }
}
Sometimes I have an instance of Child1 instantiated, and sometimes I need Child2. However, I have model that I want to pass around my application to keep everything in one place, but I want a way to make the property that holds Child1 and Child2 generic, for example:
public class BatchJob {
public List<Batch> Batches { get; set; }
}
And then later do this
public List<RequestBatch> GetBatches(...) {}
var BatchJob = new BatchJob();
BatchJob.Batches = GetBatches(...);
However, the compiler yells at me saying it can't implicitly convert Child1 to (its base type) Parent.
I get red squiggles under "= GetBatches(...." saying "Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
Is there a way to generify the Property so it can take any abstract of type Parent?
Thanks!
The code snipped you show does work. There is no compiler error:
class Program
{
static void Main()
{
var rj = new RunningJob();
rj.Property = new Child1();
rj.Property = new Child2();
}
}
public class RunningJob {
public Parent Property { get; set; }
}
public class Parent { }
public class Child1 : Parent { }
public class Child2 : Parent { }
The only issue that comes with this code is that Property is of type Parent. So you cannot call methods that are specific for Child1/Child2. This can be done using constraints on generic type parameters on class RunningJob :
public class RunningJob<TParent> where TParent : Parent
{
public TParent Property { get; set; }
}
Hence, now it is ensured that Property is of type Parent or any derived types.
One option...
public new IEnumerable<RequestBatch> GetBatches(...) {
get
{
return base.GetBatches(...).OfType<RequestBatch>();
}
}
Another...
If you don't need to modify the collection then just change from List<T> to IEnumerable<T>
More Info...
Covariance and Contravariance in Generics
A contravariance conundrum
I don't know if this is possible, but I am trying to get the Base Class instance from a Derived Class. In C#, I can use the base keyword to access properties and methods of the Base Class (of course), but I want to use base itself. Attempting to do so results in a "Use of keyword 'base' is not valid in this context" error.
Example Code
public class SuperParent
{
public int SPID;
public SuperParent()
{
}
}
public class SubChild : SuperParent
{
public SubChild(int pSPID)
{
base.SPID = pSPID;
}
public int BaseSPID
{
get
{
SuperParent sp = base;
return sp.SPID;
}
}
}
If you're working with an instance of the derived class, there is no base instance.
An example:
class A
{
public void Foo() { ... }
}
class B : A
{
public void Bar() { ... }
}
What is not possible within B:
public void Bar()
{
// Use of keyword base not valid in this context
var baseOfThis = base;
}
You can do something like this:
public void Bar()
{
base.Foo();
}
And you can add another method like
public A GetBase()
{
return (A)this;
}
And then you can
public void Bar()
{
var baseOfThis = GetBase();
// equal to:
baseOfThis = (A)this;
}
So this GetBase() method is probably what you want.
The punchline is: If you have an instance of B, it inherits all properties and the non-overriden behaviour of A, but it does not consist of an instance of B which holds an (hidden but automatic) reference to an instance of A. You can cast your B instance to A, but it remains to be an instance of B.
Well you not provide code for your question, but i supsect you want something like
class Base
{
public virtual void Foo()
{
Console.WriteLine("base");
}
}
class Derived : Base
{
public override void Foo()
{
Console.WriteLine("derived");
}
//// bad
//public Base MyBase
//{
// get
// {
// return base; // Use of keyword 'base' is not valid in this context
// }
//}
// work but...
public Base MyBase
{
get
{
return (Base)this;
}
}
}
But keep in mind that MyBase is really of type Derived
new Derived().MyBase.Foo(); // output "derived"
the problem hasn't been explained as clearly as it could. however, typically, you may be better to use an abstract base class and methods and then override the required methods. you can then use the base.method as required in this case (otherwise you'll have just spun up an instance of the derived class).
public abstract class foo {
public virtual void bar(){..}
}
public class footwo : foo {
public override void bar(){
// do somethng else OR:
return base.bar();
}
}
}
The derived instance IS the base instance. It's just one object instance in memory.
example:
public class A : B
{
}
var thing = new A();
thing is an instance of an A, and is also an instance of a B.
You could for example, write this line:
B thing2 = thing;
Point 1: if you want to create the base class instance within child class than it does not worth. You already have public things accessible in child.
Point 2: If you have initialized child class and now want to get base class "instance" then how can you get that if it's not initialized(Because now the base class instance is not present in the physical memory, and there is just child class instance there)?
I interpreted what they were asking a bit differently than the other answers here so I figured I would offer my $0.02.
// Create a "Parent" class that has some attributes.
public class Parent
{
public string attribute_one { get; set; }
public string attribute_two { get; set; }
public string attribute_three { get; set; }
}
// Define a class called "Child" that inherits the
// attributes of the "Parent" class.
public class Child : Parent
{
public string attribute_four { get; set; }
public string attribute_five { get; set; }
public string attribute_six { get; set; }
}
// Create a new instance of the "Child" class with
// all attributes of the base and derived classes.
Child child = new Child {
attribute_one = "interesting";
attribute_two = "strings";
attribute_three = "to";
attribute_four = "put";
attribute_five = "all";
attribute_six = "together";
};
// Create an instance of the base class that we will
// populate with the derived class attributes.
Parent parent = new Parent();
// Using reflection we are able to get the attributes
// of the base class from the existing derived class.
foreach(PropertyInfo property in child.GetType().BaseType.GetProperties())
{
// Set the values in the base class using the ones
// that were set in the derived class above.
property.SetValue(parent, property.GetValue(child));
}
The result is a new object populated with the base class properties of the child class.
class Parent
{
private Parent _parent;
public Parent()
{
_parent = this;
}
protected Parent GetParent()
{
return _parent;
}
}
class Child : Parent
{
private Parent _parent;
public Child()
{
_parent = base.GetParent();
}
}
Say I have a class
class Object
{
Vector2 positon;
}
This position is editable in the propert grid, how would I be able to set this as not browasable / read only in a class that inherits from object. I know the [Browsable(false)] and [ReadOnly(true)] tags but this will set the it for all Objects, which I do not desire.
Declare position property as virtual and override it on derived types.
public class Class1
{
public virtual string Lol { get; set; }
}
class Class1Impl1 : Class1
{
[Browsable(false)]
[ReadOnly(false)]
public override string Lol
{
get
{
return base.Lol;
}
set
{
base.Lol = value;
}
}
}
class Class1Impl2 : Class1
{
[Browsable(true)]
[ReadOnly(true)]
public override string Lol
{
get
{
return base.Lol;
}
set
{
base.Lol = value;
}
}
}
Doing it at runtime is a different question, IsBrowsable and IsReadOnly are readonly properties. You should google to know if there is posible to change the instances of this attributes at runtime, which I think is not.
I don't think it's possible to change the browseable attribute at runtime (and I don't understand the point of doing that), but you can have a method check your conditions and allow/disallow writing of the property. If that's good enough, I'll be glad to mock something up if you want.
EDIT:
class SomeClass
{
private Object _foo;
private Object _bar;
public Object Foo
{
get
{
return _foo;
}
set
{
if (_bar != _foo) // replace with your test
{
_foo = value;
}
}
}
}
I have 2 classes, each returns itself in all of the function:
public class Parent{
public Parent SetId(string id){
...
return this
}
}
public class Child : Parent{
public Child SetName(string id){
...
return this
}
}
I want to enable this kind of API:
new Child().SetId("id").SetName("name");
SetName cannot be accessed since SetId returns Parent and SetName is on the Child.
How?
If you really want this fluent behavior, and the Parent class can be made abstract, then you could realize it like this:
public abstract class Parent<T> where T : Parent<T>
{
public T SetId(string id) {
return (T)this;
}
}
public class Child : Parent<Child>
{
public Child SetName(string id) {
return this;
}
}
It is now possible to write:
new Child().SetId("id").SetName("name");
I might be missing the point here, but it looks like your really just trying to set properties. If you expose them as properties you can use an object initializer call.
var child = new Child()
{
Id = value1;
Name = value2;
}
You can also call a method instead of setting a value inside the intializer.
I find it odd that you want to return a reference to the current instance of a class from within the current instance. Would you not already have such a reference, in order to access the properties and methods of the object? Might you be thinking about CLONING?
Unless I am missing something about your model, it seems that a propely set up initialization scheme, some boring Property definitions, and perhaps a factory class might be more like what you are looking for. It also seems like you MIGHT consider setting up your Parent with ID as an immutable property, although your requirements might create a bona-fide reason for doing so.
Here are some potentially useful class def's. It is early here in St. Louis, and I am not properly caffienated yet, so I might be missing something . . . ;-)
The Parent:
public class Parent
{
protected string _id;
// Protected default constructor so tht this class can be inherited:
protected Parent() { }
// REquired to set ID at initialization;
public Parent(String ID)
{
_id = ID;
}
// Read-only:
public String ID
{
get { return _id; }
}
// This seems a little dodgy. Why would you want to return a reference
// to the current instance as a result of resetting the ID?
public Parent SetID(String ID)
{
_id = ID;
return this;
}
}
A Parent Factory:
public class ParentFactory
{
public static Parent NewParent(String ID)
{
Parent newParent = new Parent(ID);
return newParent;
}
}
The Child:
public class Child : Parent
{
private string _name;
// Protected default constructor so tht this class can be inherited:
protected Child() { }
// Initialize a new Child with the ID property required for the parent:
public Child(String ID)
{
base.SetID(ID);
}
// Initialize a new child with both properties set:
public Child(String ID, String Name) : this(ID)
{
_name = Name;
}
// This could be read-only as well:
public String Name
{
get { return _name; }
set { _name = value; }
}
// Again, seems kinda dodgy:
public Child SetName(String name)
{
return this;
}
}
A Child Factory:
public class ChildFactory
{
public static Child NewChild(String ID)
{
Child newChild = new Child(ID);
return newChild;
}
public static Child NewChild(String ID, String Name)
{
Child newChild = new Child(ID, Name);
return newChild;
}
}
Davide Piras is right, a way to do it is to use a virtual method, or better an interface.
See this code
public interface INode
{
INode SetName(string aName);
INode SetId(string aId);
}
public class Parent : INode
{
public virtual INode SetId(string id)
{
...
return this
}
public virtual INode SetName(string aId)
{
return this;
}
}
public class Child : Parent
{
public override INode SetName(string id)
{
...
return this;
}
}
It looks like you're trying to create a fluent interface. Are you sure that this is going to be the easiest way for developers to use these classes?
How about going with simple old properties for 'Name' and 'Id'? This is nice and easy to use, especially when using Collection Initialiser syntax.
I found a similar question but for java language here: Way to make Java parent class method return object of child class
tried to compile it but does not work, see my snipped and see my comment, basically looks like in Java we can cast this to T but in C# now. interesting...
(this is not the solution to your question I'm just reporting what I tried to do and how far I was able to get, if anybody knows some magic to get this working keeping such design... welcome :) )
class Program
{
static void Main(string[] args)
{
var obj = new Child().SetId("id").SetName("aaa");
}
}
public class Parent<T>
{
public virtual T SetId(string id)
{
// this does not work
return (T)this;
// this compiles but is NOT what we want :(
//return default(T);
}
}
public class Child : Parent<Child>
{
public Child SetName(string name)
{
return this;
}
}
What's wrong with this:
((Child)(new Child().SetId("id")).SetName("name");
The explanation here is that although the runtime type of the object is Child, the static type inference C# uses when it compiles the expression you wanted to support is concluding that the static type of SetId("id") is Parent. And it is, since SetId is defined in the Parent class.
In fact your object is of type Child, and has a SetName method. Thus, SetName is available to you, but only if you tell C# to treat the object as a Child. In your expression you don't, and but since Parent doesn't have a SetName method, your code won't typecheck, so it won't compile.
If you do the coersion C# will check the type just in case, but then it will do the invocation you had in mind.
I have an abstract base class and I want to declare a field or a property that will have a different value in each class that inherits from this parent class.
I want to define it in the baseclass so I can reference it in a base class method - for example overriding ToString to say "This object is of type property/field".
I have got three ways that I can see of doing this, but I was wondering - what is the best or accepted way of doing this? Newbie question, sorry.
Option 1:
Use an abstract Property and override it on the inherited classes. This benefits from being enforced (you have to override it) and it is clean. But, it feels slightly wrong to return a hard-code value rather than encapsulate a field and it is a few lines of code instead of just. I also have to declare a body for "set" but that is less important (and there is probably a way to avoid that which I am not aware of).
abstract class Father
{
abstract public int MyInt { get; set;}
}
class Son : Father
{
public override int MyInt
{
get { return 1; }
set { }
}
}
Option 2
I can declare a public field (or a protected field) and explicitly override it in the inherited class. The example below will give me a warning to use "new" and I can probably do that, but it feels wrong and it breaks the polymorphism, which was the whole point. Doesn't seem like a good idea...
abstract class Mother
{
public int MyInt = 0;
}
class Daughter : Mother
{
public int MyInt = 1;
}
Option 3
I can use a protected field and set the value in the constructor. This seems pretty tidy but relies on me ensuring the constructor always sets this and with multiple overloaded constructors there is always a chance some code path won't set the value.
abstract class Aunt
{
protected int MyInt;
}
class Niece : Aunt
{
public Niece()
{
MyInt = 1;
}
}
It's a bit of a theoretical question and I guess the answer has to be option 1 as it is the only safe option but I am just getting to grips with C# and wanted to ask this of people with more experience.
Of the three solutions only Option 1 is polymorphic.
Fields by themselves cannot be overridden. Which is exactly why Option 2 returns the new keyword warning.
The solution to the warning is not to append the “new” keyword, but to implement Option 1.
If you need your field to be polymorphic you need to wrap it in a Property.
Option 3 is OK if you don’t need polymorphic behavior. You should remember though, that when at runtime the property MyInt is accessed, the derived class has no control on the value returned. The base class by itself is capable of returning this value.
This is how a truly polymorphic implementation of your property might look, allowing the derived classes to be in control.
abstract class Parent
{
abstract public int MyInt { get; }
}
class Father : Parent
{
public override int MyInt
{
get { /* Apply formula "X" and return a value */ }
}
}
class Mother : Parent
{
public override int MyInt
{
get { /* Apply formula "Y" and return a value */ }
}
}
Option 2 is a non-starter - you can't override fields, you can only hide them.
Personally, I'd go for option 1 every time. I try to keep fields private at all times. That's if you really need to be able to override the property at all, of course. Another option is to have a read-only property in the base class which is set from a constructor parameter:
abstract class Mother
{
private readonly int myInt;
public int MyInt { get { return myInt; } }
protected Mother(int myInt)
{
this.myInt = myInt;
}
}
class Daughter : Mother
{
public Daughter() : base(1)
{
}
}
That's probably the most appropriate approach if the value doesn't change over the lifetime of the instance.
You could do this
class x
{
private int _myInt;
public virtual int myInt { get { return _myInt; } set { _myInt = value; } }
}
class y : x
{
private int _myYInt;
public override int myInt { get { return _myYInt; } set { _myYInt = value; } }
}
virtual lets you get a property a body that does something and still lets sub-classes override it.
option 2 is a bad idea. It will result in something called shadowing; Basically you have two different "MyInt" members, one in the mother, and the other in the daughter. The problem with this, is that methods that are implemented in the mother will reference the mother's "MyInt" while methods implemented in the daughter will reference the daughter's "MyInt". this can cause some serious readability issues, and confusion later down the line.
Personally, I think the best option is 3; because it provides a clear centralized value, and can be referenced internally by children without the hassle of defining their own fields -- which is the problem with option 1.
You could define something like this:
abstract class Father
{
//Do you need it public?
protected readonly int MyInt;
}
class Son : Father
{
public Son()
{
MyInt = 1;
}
}
By setting the value as readonly, it ensures that the value for that class remains unchanged for the lifetime of the object.
I suppose the next question is: why do you need it?
If you are building a class and you want there to be a base value for the property, then use the virtual keyword in the base class. This allows you to optionally override the property.
Using your example above:
//you may want to also use interfaces.
interface IFather
{
int MyInt { get; set; }
}
public class Father : IFather
{
//defaulting the value of this property to 1
private int myInt = 1;
public virtual int MyInt
{
get { return myInt; }
set { myInt = value; }
}
}
public class Son : Father
{
public override int MyInt
{
get {
//demonstrating that you can access base.properties
//this will return 1 from the base class
int baseInt = base.MyInt;
//add 1 and return new value
return baseInt + 1;
}
set
{
//sets the value of the property
base.MyInt = value;
}
}
}
In a program:
Son son = new Son();
//son.MyInt will equal 2
You can go with option 3 if you modify your abstract base class to require the property value in the constructor, you won't miss any paths. I'd really consider this option.
abstract class Aunt
{
protected int MyInt;
protected Aunt(int myInt)
{
MyInt = myInt;
}
}
Of course, you then still have the option of making the field private and then, depending on the need, exposing a protected or public property getter.
I'd go with option 3, but have an abstract setMyInt method that subclasses are forced to implement. This way you won't have the problem of a derived class forgetting to set it in the constructor.
abstract class Base
{
protected int myInt;
protected abstract void setMyInt();
}
class Derived : Base
{
override protected void setMyInt()
{
myInt = 3;
}
}
By the way, with option one, if you don't specify set; in your abstract base class property, the derived class won't have to implement it.
abstract class Father
{
abstract public int MyInt { get; }
}
class Son : Father
{
public override int MyInt
{
get { return 1; }
}
}
I did this...
namespace Core.Text.Menus
{
public abstract class AbstractBaseClass
{
public string SELECT_MODEL;
public string BROWSE_RECORDS;
public string SETUP;
}
}
namespace Core.Text.Menus
{
public class English : AbstractBaseClass
{
public English()
{
base.SELECT_MODEL = "Select Model";
base.BROWSE_RECORDS = "Browse Measurements";
base.SETUP = "Setup Instrument";
}
}
}
This way you can still use fields.
The example implementation when you want to have an abstract class with implementation. Subclasses must:
Parameterize the implementation of an abstract class.
Fully inherit the implementation of the abstract class;
Have your own implementation.
In this case, the properties that are necessary for the implementation should not be available for use except for the abstract class and its own subclass.
internal abstract class AbstractClass
{
//Properties for parameterization from concrete class
protected abstract string Param1 { get; }
protected abstract string Param2 { get; }
//Internal fields need for manage state of object
private string var1;
private string var2;
internal AbstractClass(string _var1, string _var2)
{
this.var1 = _var1;
this.var2 = _var2;
}
internal void CalcResult()
{
//The result calculation uses Param1, Param2, var1, var2;
}
}
internal class ConcreteClassFirst : AbstractClass
{
private string param1;
private string param2;
protected override string Param1 { get { return param1; } }
protected override string Param2 { get { return param2; } }
public ConcreteClassFirst(string _var1, string _var2) : base(_var1, _var2) { }
internal void CalcParams()
{
//The calculation param1 and param2
}
}
internal class ConcreteClassSecond : AbstractClass
{
private string param1;
private string param2;
protected override string Param1 { get { return param1; } }
protected override string Param2 { get { return param2; } }
public ConcreteClassSecond(string _var1, string _var2) : base(_var1, _var2) { }
internal void CalcParams()
{
//The calculation param1 and param2
}
}
static void Main(string[] args)
{
string var1_1 = "val1_1";
string var1_2 = "val1_2";
ConcreteClassFirst concreteClassFirst = new ConcreteClassFirst(var1_1, var1_2);
concreteClassFirst.CalcParams();
concreteClassFirst.CalcResult();
string var2_1 = "val2_1";
string var2_2 = "val2_2";
ConcreteClassSecond concreteClassSecond = new ConcreteClassSecond(var2_1, var2_2);
concreteClassSecond.CalcParams();
concreteClassSecond.CalcResult();
//Param1 and Param2 are not visible in main method
}