I have 1 abstract class that is calling a static method which up until now didn't require any parameters. This has recently changed. In reality the static method exists in another class and sets the value of BaseMessageDirectory, but in this example below I have simplified things...
So now I want to create my derived classes in such a way that they can initialize some required properties in the parent class during the inheritance, is this possible?
For example....
public abstract class ParentClass
{
protected string BaseMessageDirectory;
protected ParentClass(EnumOperationType operationType)
{
if(operationtype == 1)
{
BaseMessageDirectory = "one";
}
else
{
BaseMessageDirectory = "two";
}
}
}
Yes, you can define a constructor, and all child classes will have to call it:
public class Child : ParentClass
{
public Child() : base(EnumOperationType.One) { ... }
}
Related
I have the following method in the base class:
public class Base
{
protected string Make(string param)
{
return this.ClientID + "_" + configParam;
}
}
And i have another class
public class Class2 : Base
{
}
And
public class Class3 : Base
{
//HERE i would like to call Make but with the THIS as Class2, not the current - Class3.
}
Is this possible?
Thanks.
Suppose you want only subclasses of Base to invoke Make, even if it's not their own Make, you can add a protected invoker method (I call it InvokeSiblingMake):
public class Base
{
private string ClientID;
protected string Make(string param)
{
return this.ClientID + "_" + param;
}
protected void InvokeSiblingMake(Base other)
{
other.Make("hello world");
}
}
public class Class2 : Base
{
}
public class Class3 : Base
{
//HERE i would like to call Make but with the THIS as Class2, not the current - Class3.
public void Test(Class2 other)
{
InvokeSiblingMake(other);
}
}
With the structure of the classes that you have Class3 is a sibling of Class2. You inherit from your parents, not your brother and sister. This means there is no way to cleanly call a method on Class2 from within Class3 through means of base.
There are ways around that by giving a Class2 member variable to Class3, however at that point you're not using inheritance. In that approach, Class2 could inherit from System.Object, System.DateTime or any other class you may create yourself. Then you're acting on the object set as the property, and not through inheritance.
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 have a base class that has methods that use a generic type in C#, I then have other classes that inherit from these, I want to specify the type in the parent class to avoid angle brackets everywhere...
Here's a sample method from my base class class CBaseHome
public List<T> fetchAll<T>(CBaseDb db, bool includeEmpty = true) where T : CBaseTable, new()
{
List<T> retVal = new List<T>();
...
return retVal;
}
I the have a parent class that inherits from this class, (without overriding this function)
In the class that then consumes this I have the following code...
List<student> students = new limxpoDB.Home.student().fetchAll<student>(db, false);
so the Home.student class here inherits the CBaseHome class, and student inherits the CBaseTable...
I'd like to be able to say in the Home.student class that the only valid generic type for that class is student so that my consuming code looks like...
List<student> students = new limxpoDB.Home.student().fetchAll(db, false);
I realise here that the difference is minute, but I also use this library in some VB>Net code where it looks terrible...
Any ideas?
Thanks
Generic type parameters on a method cannot be imposed by a child class. So if I have:
public class Parent {
public List<T> GetStuff<T>() { ... }
}
I can not do:
public class Child : Parent {
// This is not legal, and there is no legal equivalent.
public List<ChildStuff> GetStuff<ChildStuff>() { ... }
}
What you can do is make the parent class generic, rather than it's method:
public class Parent<T> {
public List<T> GetStuff() { ... }
}
public class Child : Parent<ChildStuff> {
// GetStuff for Child now automatically returns List<ChildStuff>
}
I have this base class having the following interface:
abstract class Base
{
abstract public object Val
{
get;
}
}
For any derived classes, Val's value must be specified at object creation time.
The question is: How can I make a derived class do this (hopefully at compile time)?
I tried adding a constructor:
abstract class Base
{
public Base(object value)
{
val = value;
}
private object val;
...
}
But as you can see then I had to declare a private field to store value in it (because Value is read-only).
The problem arises because I want to add some kind of effect to derived classes using the Decorator/Wrapper pattern introduced in GoF Design Patterns. But because I have declared the field inside Base class, the decorators keep saving a copy of the same data and I end up wasting memory.
Try this instead:
abstract class Base
{
public Base(object val)
{
this.Val = val;
}
public object Val { get; private set; }
}
That way, your derived class doesn't need its own field:
public class Derived : Base
{
public Derived(object val) : base(val) { }
}
If it is a decorator, then don't have a field:
public override object Val {
// add any decoration effects here if needed
get { return tail.Val; }
}
Where tail is the thing you are decorating.
However, it sounds like you mean inheritance (not decoration) - if so:
abstract class BaseClass {
protected BaseClass(object val) {...}
}
class ConcreteType : BaseClass {
public ConcreteType(object val)
: base(val) { }
}
Here the base class could even handle the storage etc.
I have a baseclass which has public contructors.
The baseclass is not sealed and is not abstract.
There is one constructor which I desire to be sealed. Is this possible?
My current attempt results in syntax error saying the constructor cannot be sealed.
public sealed MyBase(string someParam)
Additional:
I wish to be able to instantiate the base class directly and have access to the sealed constructor. Derived classes cannot use that constructor via the derived constructors.
E.g.
public MyDerived() : base(string cant_access_my_sealed_constructor)
You can't do that. If the constructor is public, you can call it from constructors of derived classes. But you can do something close – you can have a private constructor and a public static method that calls it:
class MyBase
{
private MyBase(string someParam)
{
// some code
}
public static MyBase Create(string someParam)
{
return new MyBase(someParam);
}
protected MyBase() // or some other protected or public constructor
{ }
}
class MyDerived : MyBase
{
public MyDerived()
: base("foo") // won't compile, as requested
{ }
}
All constructors are "sealed" in that they cannot be "overridden." They can only be called from the constructor in a child class.
If you are hoping to prevent child classes from having a constructor with the same signature, that cannot be done.
Based on the additional information you added to the post, it sounds like what you want to do is make your constructor private, as Kyle suggested. This will prevent the child class from calling the constructor, but it won't prevent it from taking the same types of arguments:
public class Foo
{
private Foo(string s){
}
// Allowed
public Foo() : this("hello") {
}
}
public class Bar : Foo
{
// Allowed
public Bar(string s) : base(){
}
// Not allowed
public Bar(string s) : base(s){
}
}
If you want to prevent the constructor from being called by inherited classes, just mark it private.
Constructors aren't inherited by a child class, you have to explicitly call a base constructor if desired.
This code will call the base class' no-parameter constuctor when an instance of the child class is instantiated. Without it, the base class' constructor won't be called when creating a new instance of the child class.
public class A
{
public A()
{
}
}
public class B : A
{
public B()
: base()
{
}
}