using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new B("MyName").Name);
}
}
abstract class A
{
public A(string name)
{
this.GetType().GetField("Name").SetValue(this, name);
}
}
class B : A
{
public B(string name)
: base(name)
{
}
public string Name
{
set;
get;
}
}
}
Is it possible to do something like that?
I can't stress how very, very, very bad this is. You are creating an inverse coupling that is convoluted, confusing and contrived, severely lacking in clarity, failing best practices and object oriented principals, which is going to create a maintenance and management nightmare for people implementing derivatives of your abstract class. Do the right thing!!
abstract class A
{
protected A(string name)
{
Name = name;
}
public abstract string Name
{
get;
protected set;
}
}
class B: A
{
public B(string name) : base(name)
{
}
private string m_name;
public override string Name
{
get { return "B Name: " + m_name; }
protected set
{
m_name = value;
}
}
}
It is possible, but i wouldn´t recommend to do that. The problem is that your base class knows to much about the class that are derived from it.
When you derive a class from your abstract base class that does not define the property Name you get an Exception on runtime.
If you expect that each class, that is derived from your base class, has a property Name, then it would be easier to define the Property Name in your abstract base class and set the property with you constructor.
It's really bad form to do that. Generally you should just call a method like 'SetPossibleData()', and force all children to implement it in a fashion they decide.
Why do you need to do this?
Use GetProperty() Method,
public A(string name)
{
this.GetType().GetProperty("Name").SetValue(this,name,null);
}
It would be really straight forward if every class initializes the fields and properties it defines. Why does B expect the base class initialize its Name?
abstract class A
{
public A()
{
}
}
class B : A
{
// I know, its trivial, but it does the same ...
public B(string name) : base()
{
Name = name;
}
public string Name { set; get; }
}
The only thing I could think of why you wrote this code is that the base class has some logic to initialize the field. Straight forward would be to let the derived class call the logic, but initialize the field itself:
abstract class A
{
public A()
{
}
protected string GenerateName(string someArg)
{
// complicated logic to generate the name
}
}
class B : A
{
public B(string someArg) : base()
{
Name = base.GenerateName(someArg);
}
public string Name { set; get; }
}
Related
I'm having a hard time phrasing the question which is also making it hard for me to search for answers.
Here's a contrived scenario that mimics what I'd like to do:
void Main()
{
Console.WriteLine(TestClassA.MyPropertyName());
Console.WriteLine(TestClassB.MyPropertyName());
var speaker = new TestSpeaker();
speaker.Speak<TestClassA>();
speaker.Speak<TestClassB>();
}
public class TestSpeaker {
public void Speak<T>() where T : BaseClass<T> {
Console.WriteLine(/* I want to call T.MyPropertyName() here */);
}
}
public class TestClassA : BaseClass<TestClassA> {
public string Name { get; set; }
}
public class TestClassB : BaseClass<TestClassB> {
public string OtherPropertyName { get; set; }
}
public abstract class BaseClass<T> {
public static string MyPropertyName(){
return typeof(T).GetProperties().Single().Name;
}
}
The Console right now would read:
Name
OtherPropertyName
I'd like to replace my commented out code so that it would read:
Name
OtherPropertyName
Name
OtherPropertyName
if you change your Writeline to
Console.WriteLine(BaseClass<T>.MyPropertyName());
you will get what you want
Why use a static function in a base class to retrieve information about a derived class? In any case, you could implement a member function to wrap the static call:
public static string MyStaticFunction() => return "whatever";
public string MyMemberFunction() => MyStaticFunction();
But in your scenario, perhaps you should simply declare an abstract property (or function) meant to return the value you're looking for and override it in derived classes:
Base:
public abstract string MyPropertyName { get; }
Derived:
public override string MyPropertyName => nameof(OtherPropertyName); // or more complex logic
And yet another possible solution would be to pass the information to the base class's constructor as a string (or property expression should you be so inclined):
Base:
public string MyPropertyName { get; init; }
public BaseClass(string propertyName)
{
MyPropertyName = propertyName; // maybe validate that the property exists
}
Derived:
public MyTestClassB() : BaseClass(nameof(OtherPropertyName)) {}
I have a base class with is inherited by multiple derived classes. I am initializing some properties of base class in constructor. Is there any way i can make the base class property being shared by my derived objects rather than creating the same property values for each derived class object. This is really important because some of the base class property values are generated by services and sharing this can improve performance.
Below is somewhat a simple blueprint of what i am trying to say:
public class ClassA
{
//i dont want to use static here as it will be shared for multiple codes
protected string country { get; set; }
public ClassA(string code)
{
country = CallsomeService(code);
}
}
public class ClassB : ClassA
{
public ClassB(string code) : base(code)
{
//blah blah
}
public void DomeSomethingWithCountry()
{
Console.WriteLine($"doing this with {country} in classB");
}
}
public class ClassC : ClassA
{
public ClassC(string code) : base(code)
{
//blah blah
}
public void DomeSomethingWithCountry()
{
Console.WriteLine($"doing soemthing else with {country} in classC");
}
}
Now making objects like below
public void test()
{
//call service for this
var classb=new ClassB("1");
//dont call service for this
var classc=new ClassC("1");
classb.DomeSomethingWithCountry();
classc.DomeSomethingWithCountry();
//call service for this as code is different
var classb1=new ClassB("2");
}
You could store the result of having made the call statically, rather than the value itself.
public class ClassA
{
static Dictionary<string,string> codeToCountryLookup
= new Dictionary<string,string>();
protected string country { get; set; }
public ClassA(string code)
{
if(!codeToCountryLookup.ContainsKey(code))
codeToCountryLookup.Add(code,CallsomeService(code));
country = codeToCountryLookup[code];
}
}
This is not in any way threadsafe, but should give you somewhere to start.
I have an abstract class Animal, with classes that inherit variables from that class. For instance, a Name string will hold the name of the animal that class represents.
My question is, can I require that those variables be initialized in the child's constructor? I want to ensure that Cat.cs, Dog.cs, etc actually store a name. I believe I can create a virtual Start() or Awake() method, but that will only assure that the Name string have something in it, but not the actual name of the animal.
If you'll add this constructor to the base Animal class:
public abstract class Animal
{
protected Animal(string name)
{
this.Name = name;
}
public string Name { get; set; }
}
Any type derives from it will be required to supply that argument to the constructor:
public class Dog : Animal
{
public Dog(string name) : base(name)
{
}
}
See MSDN
This is almost exactly the same as haim770, but shows you can have default constructors as well (and one other thing I'll point out at the bottom)
public abstract class Animal
{
public string Name { get; private set; }
public Animal(string name)
{
Name = name;
}
}
public class Dog : Animal
{
public Dog()
: base("Rover")
{
}
public Dog(string name)
: base(name)
{
}
}
The only other thing to note here is that the constructor of Animal is not declared protected. Why? Because it doesn't really matter. Because Animal is an abstract class you can't create new instances of it anyway, so making the constructor public is functionally equivalent to making it protected in this case.
I have a class like this
public class BaseClass
{
public string Request { get; set;}
}
and I have the class like this :
public class ExtendClass : BaseClass
{
}
So actually the property Request will always be set with the name of ExtendClass. So it actually will be Request="ExtendClass"
I have many class who extend BaseClass. I know I just can pass string to it, but is that possible to do it?
You can use object.GetType which will always return the type on top in the hierarchy (so the last deriving class):
public string Request
{
get
{
return this.GetType().Name;
}
}
Name will return the short type name, without the namespace. If you want that too, you should use FullName.
You have multiple choices. For example, you can use reflections:
public string Request { get {return this.GetType().Name; }}
Or you can make it more explicit, with abstract property (and that way you can specify not only class names):
public abstract class BaseClass
{
public abstract string Request { get; }
}
class ExtendClass : BaseClass
{
public override string Request { get {return "ExtendClass"; } }
}
I'm trying to setup some classes like:
public abstract class AnimalBase {
public string SpeciesName { get; private set; }
public AnimalBase(string speciesName) {
this.SpeciesName = speciesName;
}
public abstract void CopyFrom(AnimalDefaultClass defaultVals);
}
public class Mammal : AnimalBase {
public bool WalksUpright { get; private set; }
public Mammal(string speciesName) : base(speciesName) {
this.CopyFrom(new MammalDefaultClass(speciesName));
}
public override void CopyFrom(MammalDefaultClass defaultVals) {
this.WalksUpright = defaultVals.WalksUpright;
}
public void Cripple() {
this.WalksUpright = false;
}
}
public class MammalDefaultClass : AnimalDefaultClass {
public bool WalksUpright { get; private set; }
public MammalDefaultClass(string speciesName) {
using (var dataStore = theoreticalFactory.GetDataStore()) {
this.WalksUpright = dataStore[speciesName].WalksUpright;
}
}
}
Obviously that's not quite what I'm trying to accomplish, but the idea is:
Several classes (Mammal, Fish, Insect, etc) which inherit from an abstract base (Animal).
Each child class has a corresponding class it can use (in this case to populate mutable default values) as a parameter for a method which was defined as abstract in the base class.
Each of those corresponding classes (MammalDefaultClass, FishDefaultClass, InsectDefaultClass, etc) inherit from a common base class (AnimalDefaultClass).
Those AnimalDefaultClass derivatives exist because each class of Animal will have different properties, but by definition there will always be a class capable of getting those values for any Animal.
My problem is:
That overridden version of CopyFrom(MammalDefaultClass) isn't being recognized as a valid override of the abstract CopyFrom(AnimalDefaultClass), even though MammalDefaultClass inherits from AnimalDefaultClass
Is it possible to specify a base class as an abstract member's parameter? Is there a simple* workaround? Or is this whole thing just laid out wrong?
-edit: my resolution-
After playing around some with MWB and sza's suggestions, I ended up having each subclass implement the method using the base parameter and then cast the input as appropriate, something like:
public class Mammal : AnimalBase {
...
// implements the abstract method from the base class:
public override void CopyFrom(AnimalDefaultClass defaultVals) {
this.CopyFrom((MammalDefaultClass)defaultVals);
}
public void CopyFrom(MammalDefaultClass defaultVals) {
this.WalksUpright = defaultVals.WalksUpright;
}
}
This solution forces me to always implement a CopyFrom(AnimalDefaultClass) , which was the point of the putting the abstract method in the base class in the first place.
I think you can try Abstract Factory pattern. Basically you want to handle some construction logic during the creating the object, and for each different subtype of the Product, you can do differently.
public abstract class AnimalBase
{
public string SpeciesName { get; private set; }
protected AnimalBase(string speciesName)
{
this.SpeciesName = speciesName;
}
}
public class Mammal : AnimalBase
{
public bool WalksUpright { get; set; }
public Mammal(string speciesName) : base(speciesName)
{
}
public void Cripple()
{
this.WalksUpright = false;
}
}
public interface IAnimalFactory<T> where T : AnimalBase
{
T CreateAnAnimal(string speciesName);
}
public class MammalFactory: IAnimalFactory<Mammal>
{
public Mammal CreateAnAnimal(string speciesName)
{
var mammal = new Mammal(speciesName);
var mammalDefault = new MammalDefaultClass(speciesName);
mammal.WalksUpright = mammalDefault.WalksUpright;
return mammal;
}
}
And when you want to create a sub-typed object, you can do e.g.
var mammalFactory = new MammalFactory();
var bunny = mammalFactory.CreateAnAnimal("Bunny");
So it turns out that even though MammalDefaultClass is a subclass of AnimalDefaultClass, you cannot override a function that takes an AnimalDefaultClass with one that takes a MammalDefaultClass.
Consider this block of code:
public class Dinosaur : AnimalDefaultClass;
Dinosaur defaultDinosaur;
public void makeDinosaur(AnimalDefaultClass adc)
{
adc.CopyFrom(defaultDinosaur);
}
MammalDefaultClass m;
makeDinosaur(m);
In this case MammalDefaultClass is a subclass of AnimalDefaultClass, so m can be passed to makeDinosaur as adc. Furthermore the CopyFrom for an AnimalDefaultClass only needs another AnimalDefault class, so I can pass in a dinosaur. But that class is actually a Mammal, and so needs a MammalDefaultClass, which dinosaur is not.
The work around would be to take the original type signature and throw an error if the argument is the wrong type (similar to how arrays act in Java).