Accessing subclass in base class... but different - c#

I have a base class that has a subclass (could be a struct i suppose but not sure if it's appropriate) and a method.
class Base
{
protected class SubClass
{
public string word;
public int number;
}
protected void SomeMethod()
{
this.SubClass.word //this is where I'm struggling
}
}
Then i have a couple child classes that implement my baseClass, instantiate the Base.SubClass and add some values to the instantiated class.
class ChildClass1 : Base
{
public childSubClass = new SubClass();
public void DoSomethingRidiculous()
{
childSubClass.word = "WhoFarted";
}
}
class ChildClass2 : Base
{
public childSubClass = new SubClass();
public void DoSomethingRidiculous()
{
childSubClass.word = "ItStinks";
}
}
If possible, I would like to be able to get the value of SubClass.word from within the Base class. I think that my attempt at implementing my idea is probably wrong.

I'm not sure that you really need subclassing / class nesting. Just move out class SubClass declaration and declare protected field/property of SubClass type instead.
public class SubClass
{
public string word;
public int number;
}
public class Base
{
protected SubClass subClassInstance = new SubClass();
protected void SomeMethod()
{
this.subClassInstance.word //this is where I'm struggling
}
}
Then you can access subClassInstance inside both ChildClass1 and ChildClass2

The base class has no field or property of type SubClass, so you definitely cannot do what you propose directly.
One solution would be to add the field
public childSubClass = new SubClass();
to class Base itself. Is there a problem with this?
The other solution would be to use reflection to get the value of the field, assuming that the object you are reflecting on does have such a field. This is really far-fetched and while it might technically allow you to do what you propose, it has a very bad code smell.

I'm not sure why you're making a Sub Class instead of just making those two properties of the base class, but the reason you're having trouble with this line :
this.SubClass.word //this is where I'm struggling
is because you're not instantiating SubClass as a property of the base class.

A base class can not (or should not) access members of derived classes, and usually not even know about derived classes (some exceptions apply, such as in the case of the State Pattern). If the base should have access to a member, it should be declared in the base. If derived classes should also be able to use that member, then mark the member as protected.
class Base
{
protected Foo someFoo;
void Frob()
{
// can access methods/properties of someFoo instance
}
}
class Child
{
public Child()
{
someFoo = new Foo(); // child can also access someFoo
}
}

Related

Accessing protected constructor from derived class instance

G'day Folks,
I'm struggling with what I thought was a simple issue, but I've gone blind. Obviously, I'm doing something basic very wrong, but I can't see it.
What I'm trying to do: Create an instance of a base class from a derived class instance using a protected constructor.
What's happening: The protected constructor of the base class is inaccessible inside the derived class. Message: 'BaseClass.BaseClass(List)' is inaccessible due to its protection level
Consider the following code:
class BaseClass
{
protected readonly List<int> internalStuff;
// Normal constructor for everywhere else
public BaseClass()
{
internalStuff = new List<int>();
}
// this is the constructor I want to call; it shouldn't be accessible outside the derived classes hence protected
protected BaseClass( List<int> stuff )
{
internalStuff = new List<int>(stuff);
}
}
sealed class DerivedClass : BaseClass
{
public void ConvertToBaseClass( out BaseClass newBaseClassInstance )
{
newBaseClassInstance = new BaseClass(internalStuff);
}
}
The protected constructor should be visible to the derived class, right? Why is it inaccessible?
Edited to answer some questions. The code you see is the code that exists. I created the classes in a separate file and trimmed as much as sensible.
The reason I want to convert between the classes is the base class is "light" in that it contains no unmanaged code nor holds on resources. The derived class holds resources. When I am done with the derived class, but need to maintain the basic data, I want to convert to the base class.
Here is revised code to answer some of the comments below:
public class BaseClass
{
protected readonly List<int> internalStuff;
public BaseClass()
{
internalStuff = new List<int>();
}
protected BaseClass( List<int> stuff )
{
internalStuff = new List<int>(stuff);
}
}
sealed class DerivedClass : BaseClass
{
BaseClass bc;
public void ConvertToBaseClass( out BaseClass newBaseClassInstance )
{
bc = new BaseClass(internalStuff); // <- error
newBaseClassInstance = new BaseClass(internalStuff); // <- error
}
}
Public on BaseClass did nothing, nor did I expect it to. Both BaseClass and DerivedClass are in the same assembly and namespace so are visible to each other anyway.
Even if there is a BaseClass variable internal to derived class, it gives the same inaccessible error.
DerivedClass is a derived class, go figure. Why does it not have access?
There are two flaws to your request:
the instance of DerivedClass already IS and instance of the BaseClass so there is no need to convert it!
Your DerivedClass has not implemented the constructor overload with stuff parameter so there is no way for this class to access that constructor.
If the constructor is protected, then it can only be accessed via constructors in inherting classes or the base class itself, Normally we would use syntax like this when implementing a class and we want the specific base constructor to be called, but we only want internal logic to access it:
public sealed class DerivedClass : BaseClass
{
public DerivedClass ()
: base()
{
// the base implementation has been executed.
// now perform any other init logic you need.
}
private DerivedClass (List<int> stuff)
: base(stuff)
{
// the base implementation has been executed.
// now perform any other init logic you need.
}
// this is one way to access non-public constructors
public static DerivedClass CreateAnotherInstance(List<int> stuff)
{
return = new DerivedClass(stuff);
}
}
What you may not be aware of, and the reason that you don't need a Convert method at all is that and instance of DerivedClass IS an instance of BaseClass, the following statement is valid:
DerivedClass car = new DerivedClass();
BaseClass vehicle = car;
The following will also work if you are unsure if the base object was originally a specific derived implementation:
if (vehicle is DerivedClass derivedRef)
{
Console.Out.WriteLine("It was a DerivedClass instance all along");
}
else
{
Console.Out.WriteLine("Not a DerivedClass: " + vehicle.GetType().Name);
}
If your DerivedClass instance convert method returned a new instance of BaseClass then you would have to copy across all the neccessary properties and would lose the polymorphic abilities that Inheritance provides for our classes.
In regard to your update:
The reason I want to convert between the classes is the base class is "light" in that it contains no unmanaged code nor holds on resources. The derived class holds resources. When I am done with the derived class, but need to maintain the basic data, I want to convert to the base class.
I really can't understand why you would, that's not true, I understand your reasoning, I just don't think it is a good design, even to the point that i feel very strongly against providing an answer that will help you continue down this path... this type of pattern really doesn't need to use inheritance at all... with extreme caution, as in please do not do this:
public class BaseClass
{
protected readonly List<int> internalStuff;
public BaseClass()
{
internalStuff = new List<int>();
}
protected BaseClass(List<int> stuff)
{
internalStuff = new List<int>(stuff);
}
protected BaseClass CreateAsBase()
{
return new BaseClass(internalStuff);
}
// I see little point in allowing "stuff" to be passed through
// from the caller, this class already has access to the "stuff"
// but you've already demonstrated an unual taste for hard work
protected BaseClass CreateAsBase2(List<int> stuff)
{
return new BaseClass(stuff);
}
}
sealed class DerivedClass : BaseClass
{
public BaseClass ConvertToBaseClass()
{
return base.CreateAsBase();
...
// um, if you really need to, this is how you could pass the "stuff"
// I asusme you would only do this because you were going to modify
// it in a way that the base class could not anticipate.
return base.CreateAsBase2(aModifiedListOfInternalStuff);
}
}
Usually in cases like this, either there would be a Utility class or methods to handle the processing and intensive resource requirements, and you would pass around a reference to the DTO (Data Transfer Object) so you can discard the wrapper object, but the DTO would remain intact:
public class Vehicle
{
protected readonly List<int> internalStuff;
public Vehicle()
{
internalStuff = new List<int>();
}
protected Vehicle(List<int> stuff)
{
internalStuff = new List<int>(stuff);
}
public Color Color { get; set; }
}
public sealed class Car : Vehicle
{
public Car()
: base()
{
}
private Car(List<int> stuff)
: base(stuff)
{
}
public void AddOne()
{
internalStuff.Add(1);
}
}
// Wrapper that accepts a vehicle, and does "stuff" to it
public sealed class VehicleBusinessObjectWrapper : IDisposable
{
public Vehicle Vehicle { get; private set; }
public VehicleBusinessObjectWrapper(Vehicle dto)
{
Vehicle = dto;
}
public void ChangeColour(Color newColor)
{
Vehicle.Color = newColor;
/// you know, apply modifications to the Vehicle
}
public void Dispose()
{
// clean up your resources... if there are any
// for instance, deliberately clear the reference to the original DTO, just to prove a point
Vehicle = null;
// after this point, the Vehicle Object is still intact.
}
}
public static class BusinessLogic
{
public static void Test()
{
var originalCar = new Car();
using (var processor = new VehicleBusinessObjectWrapper(originalCar))
{
// We can still access the vehicle through the processor, we don't need inheritance
if (processor.Vehicle.Color != Color.Green)
processor.ChangeColour(Color.Green);
// do other stuff on the car, or on the vehicle...
if (processor.Vehicle is Car car)
{
car.AddOne();
}
}
// reference to wrapper is now gone, but our original car/vehicle still remains.
originalCar.ToString();
Vehicle v = originalCar;
Console.WriteLine(v == originalCar); // "True"
}
}
This is by design. protected members of the base class can only be accessed on a object reference of your own type. So new BaseClass(internalStuff) is invalid. But creating your own constructor that calls through to it would be valid:
DerivedClass(List<int> stuff) : base(stuff) {
Let's look at the specifications:
ECMA-335 specification, which defines the CLI on which C# is based, says as follows:
I.8.5.3.2 Accessibility of members and nested types
snip
family [this means protected in C#] – accessible to referents that support the same type (i.e., an exact type and all of the types that inherit from it). For verifiable code (see §I.8.8), there is an additional requirement that can require a runtime check: the reference shall be made through an item whose exact type supports the exact type of the referent. [my bold] That is, the item whose member is being accessed shall inherit from the type performing the access.
ECMA-334, which defines the C# language, says:
8.5.4 Protected access
When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access shall take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class. [my bold]
So this restriction stops you from creating an instance of the base class, or indeed another derived class altogether, and calling protected base functions on it.
The constructor is no exception. You must have an instance of DerivedClass to call a protected BaseClass constructor, and you can obviously only do that if you are inside the constructor of DerivedClass.
You can call the base class contractor from the derived class's constructor.
Implementation:
public class A
{
protected List<int> MyList { get; }
public A()
{
MyList = new List<int>();
MyList.Add(1);
}
public int GetListCount()
{
return MyList.Count;
}
}
public sealed class B : A
{
public B() : base()
{
}
public A GetBase()
{
return (A)this;
}
}
Usage:
public class Program
{
public static void Main(string[] args)
{
B b = new B();
var a = b.GetBase();
Console.WriteLine(a.GetListCount());
}
}
This returns 1
... I am done with the derived class, but need to maintain the basic data ...
Well I wouldn't start from here... Instead of trying to solve this problem with inheritance, I would recommend solving it with composition.
Introduce a type to represent the structure of your basic data. Perhaps an interface to represent your basic functions (if any). Then your heavy resource classes can hold a reference to the basic data.
When you are done with the heavy class, you can keep a reference to the basic data and allow the heavy class to be garbage collected.

Subclassing and generics in C#

I want to subclass a large number of classes so that they will all contain a certain set of the same properties. What would be the right way to do it in order to avoid repetition? I thought of using generics like:
public class SuperT<T> : T
{
//the same set of properties
}
But the compiler says
Cannot derive from 'T' because it is a type parameter
EDIT: I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "Radius". (So that I would use SuperImage element in XAML and when I set it's Radius property from XAML, I will be able to run some certain logic.)
One other way I just thought of right now is using T4 templates. I wonder if there is a way to do this with generics without resorting to templates? I cannot understand why the compiler rejects it.
If these classes all share a common base class or common interface you could write an extension method.
public static class ShapeExetnsionsExtLib
{
public static double Radius(this ShapeBase shape){
return /*calculate radious*/;
}
}
From comments
I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "radius".
Yes they share common base classes but I cannot add anything new to them.
I don't think generics have anything to do with this, however inheritance is probably what you're looking for.
There are two types of inheritance that you can use to subclass, and extension methods work to "superclass"... sort of.
Is-A inheritance
Has-A inheritance
And to simply add a similar method to a bunch of third party objects, you'll use an extension method.
Is-A inheritance
Use a base class if you've got similar method implementations.
public abstract class BaseFoo {
public void Bar() {
// actual code
}
}
public class Foo : BaseFoo
{
}
var foo = new Foo();
foo.Bar();
Use an Interface if you need to implement the same method on each class.
public interface IFoo {
void Bar();
}
public class Foo : IFoo {
public override void Bar(){
// bar implementation
}
}
var foo = new Foo();
foo.Bar();
Combining the two is also allowed, but you can only inherit on base class, where you can inherit multiple interfaces.
Has-A inheritance
This is particularly useful with dependency injection, but it's simply the notion that you have an instance of another class to work with. It's essentially a wrapper class for you to work with.
public class Foo {
private readonly ThirdPartyFoo _tpFoo;
void Foo(ThirdPartyFoo tpFoo) {
_tpFoo = tpFoo;
}
public void Bar(){
// now I can do something with _tpFoo;
_tpFoo.Bar();
}
}
var tpFoo = new ThirdPartyFoo();
var foo = new Foo(tpFoo);
foo.Bar(); // invokes the underlying tpFoo
Lastly, if you just need to add a method to existing classes, then you create an extension method.
public static class ViewExtensions()
{
// this assumes your Image, Button, Label all inherit from View.
public static Whatever Radius(this View view) {
// do your radius work.
}
}
Just Use a base class:
public class Base
{
public int Id { get; set; }
public string Name { get; set; }
}
And inherite from it:
public class A : Base
{
}
public class B : Base
{
}
In general, you want to use one of the answers already posted about using a base class and inheriting from that. However, if the classes are in a third party library and are marked as sealed, then you will need to create a wrapper class to use as a base class.
(Note that this option is a workaround and doesn't truly inherit from the third party class, so things in that class that are marked as protected won't be accessible without a liberal use of reflection.)
// The sealed class within another library
public sealed ThirdPartyClass
{
public ThirdPartyClass(int i) { }
public int SomeProperty { get; set; }
public int SomeMethod(string val) { return 0; }
public static void SomeStaticMethod() { }
}
// The wrapper class to use as a pseudo base class for ThirdPartyClass
public class BaseClass
{
private ThirdPartyClass _obj;
public BaseClass(int i) { _obj = new ThirdPartyClass(i); }
public int SomeProperty
{
get { return _obj.SomeProperty; }
set { _obj.SomeProperty = value; }
}
public int SomeMethod(string val) { return _obj.SomeMethod(val); }
public static SomeStaticMethod() { ThirdPartyClass.SomeStaticMethod(); }
}
// The child class that inherits from the "base" BaseClass
public class ChildClass : BaseClass
{
}
First of all, this might be a logical problem. What if you are going to extend a sealed class? Or Int32 class? Delegate?
Anyway, the way I recommend is to create an interface and implement all the functions you need in the subclass.

What is the purpose of abstract properties, when we still can use them in our abstract class?

Let's see the example at first:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Person p = new Manager();
Manager p2=new Manager();
p.Name = "Ahmad";
p.Introduce();
p.SayHello();
p2.SayHello();
p2 = (Manager)p;
p2.SayHello();
}
}
public abstract class Person
{
protected Person()
{
Name = "Reza";
Introduce();
}
public abstract string Name { get; set; }
public void SayHello()
{
Name = "Ali";
MessageBox.Show(Name);
}
public abstract void Introduce();
}
public class Manager : Person
{
public new void SayHello()
{
MessageBox.Show("Test2");
}
public override string Name { get; set; }
public override void Introduce()
{
MessageBox.Show("Hello " + Name);
}
}
}
at first i hadn't written constructor for base class.
as far as i know the purpose of abstract method is to force the derived class to implement from it, and because of that we can't implement abstract methods in base class.
then i added an abstract property. and i saw that we can initialize that property in base class and using it.
1st: Wasn't the purpose of abstract to just declare them and let derived class to implement it?
Why can we use the property in base class?
we could just implement a non-abstract property at first, and it would make no difference.
then i added the constructor and things get more complicated. we can use Introduce() method in constructor to call Introduce() from Child class (i understand that from debugger).
so Child inherits from Father here, but we call a method in Child from Father, which is strange and is somehow against the rules of inheritance.
2nd: What have i missed?
Edit:
Wasn't the purpose of abstract to just declare them and let derived
class to implement it? Why can we use the property in base class?
You can't use the abstract property in the base class, as you cannot instantiate it directly. You'd create an abstract property for the same reasons you'd want to create an abstract method, which is make sure your derived types implement it.
Your Name property isn't actually using the base-class instance. When called from SayHello, it will go to your derived-type implementation of Name and use that.
So Child inherits from Father here, but we call a method in Child from
Father, which is strange and is somehow against the rules of
inheritance. What have i missed?
It's not only strange, its an error which might cause a run-time exception, for the fact that the child object hasn't been initialized yet. If you were to access any member of Manager that are instantiated via managers constructor (not via field initialization) inside Introduce, you would get an exception:
public class Manager : Person
{
public Manager()
{
s = "Hello";
}
private string s;
public override string Name { get; set; }
public override void Introduce()
{
Console.WriteLine(s.ToLower());
}
}
When you now call Introduce, you'll see a NullReferenceException, as s hasn't been initialized yet.
If you want to call an abstract method on derived type, make sure you do it after object instantiation. Perhaps via an Initialize method on the base.
You can read Virtual member call in a constructor for more information:
if you make a virtual method call in a constructor, and it is not the
most derived type in its inheritance hierarchy, that it will be called
on a class whose constructor has not been run, and therefore may not
be in a suitable state to have that method called.

How to set the fields of a derived class?

I've 2 classes: "RootClass", and "SubClass". SubClass is derived from RootClass. How do I make a constructor in RootClass, which can set values to fields found in SubClass?
I tried:
Set the subclass's value from the root's constructor, but it doesn't see the subclass's fields.
Create a constructor in SubClass, that doesn't seem to happen. Also tried setting the constructor in root to virtual, so the sub constructor may override it, no luck either.
Instantiate SubClass in RootClass's constructor which just seem stupid.
Basically I want to have 2 classes. The SubClass is the same as RootClass with a few additional fields, which i cant seem to apply a value to.
Depending on a logic I either create a root or sub.
Clearly I'm on the wrong path here, how do I do this?
A base class wouldn't have knowledge of it children classes. What you are saying is either wrong OOP or a very unusual scenario,
How do I make a constructor in RootClass, which can set values to fields found in SubClass
You can't - as far as RootClass is concerned, SubClass doesn't exist.
Also tried setting the constructor in root to virtual, so the sub constructor may override it
You can't - constructors aren't inherited, so there's no concept of "virtual" constructors.
Here's the typical pattern for "chaining" constructors:
public class RootClass
{
public RootClass(int rootProperty)
{
this.RootProperty = rootProperty;
}
public int RootProperty {get; set;}
}
public class SubClass : RootClass
{
v--- call the base constructor
public SubClass(int rootProperty, string subProperty) : base(rootProperty)
{
this.SubProperty = subProperty;
}
public string SubProperty {get; set}
}
Perhaps you're looking for a way for SubClass to call the RootClass constructor?
public class RootClass
{
public RootClass(int foo)
{
}
}
public class SubClass: RootClass
{
public SubClass(int foo)
: base(foo) // calls RootClass constructor
{
// now set Subclass fields
}
}
You cannot access any member of the derived class from the root class.
The typical design pattern is to create a method:
virtual void Init(int a, int b) {}
in your base class, where the parameters are whatever information the derived classes would require to perform self-initialization. Call this from the constructor of the root class.
The derived class would then require a constructor
SubClass() : base() { }
which would guarantee the root class constructor is called, and then its own init method is called.
In this case, however, your best design pattern is to simply subclass.
Suppose the RootClass has member int a and the Subclass int b:
class RootClass {
int a;
RootClass(int a) {
this.a = a;
}
}
class SubClass {
int b;
SubClass(int a, int b) : base(a) {
this.b = b;
}
}
In general, base classes should not have knowledge of their subclasses' implementation details. You should be able to provide your own constructor in the subclass to instantiate its fields, like so:
class SubClass : RootClass
{
private bool subClassfield;
public SubClass() : base()
{
subClassField = true;
}
}
Does that not work as expected? Note the : base() expression, which ensures the SubClass's constructor calls the base class's constructor to guarantee the base class is initialized before proceeding.
A class can not know about the implementation of all the classes that inherit from it.

Is there a way to reach a `protected` member of another object from a derived type?

class MyBase
{
protected object PropertyOfBase { get; set; }
}
class MyType : MyBase
{
void MyMethod(MyBase parameter)
{
// I am looking for:
object p = parameter.PropertyOfBase; // error CS1540: Cannot access protected member 'MyBase.PropertyOfBase' via a qualifier of type 'MyBase'; the qualifier must be of type 'MyType' (or derived from it)
}
}
Is there a way to get a protected property of a parameter of a type from an extending type without reflection? Since the extending class knows of the property through its base type, it would make sense if possible.
Last time I faced a similar problem, I used the solution of adding a protected static method to the base:
class MyBase
{
protected object PropertyOfBase { get; set; }
protected static object GetPropertyOfBaseOf(MyBase obj)
{
return obj.PropertyOfBase;
}
}
class MyType : MyBase
{
void MyMethod(MyBase parameter)
{
object p = GetPropertyOfBaseOf(parameter);
}
}
No, you can't do this.
You're only allowed to access protected members of objects of the accessing type (or derived from it). Here, we don't know whether the parameter is of type MyType or SomeOtherCompletelyDifferentType.
EDIT: The relevant bit of the C# 3.0 spec is section 3.5.3:
When a protected instance member is
accessed outside the program text of
the class in which it is declared, and
when a protected internal instance
member is accessed outside the program
text of the program in which it is
declared, the access must take place
within a class declaration that
derives from the class in which it is
declared. Furthermore, the access is
required to take place through an
instance of that derived class type or
a class type constructed from it. This
restriction prevents one derived class
from accessing protected members of
other derived classes, even when the
members are inherited from the same
base class.
There's a good reason you can't do this. Suppose someone writes:
class Other : MyBase { }
new MyType().MyMethod(new Other());
If the language allowed what you're asking for, you could violate the assumed invariants of Other by modifying the value of PropertyOfBase.
I think you should ask yourself if there is a better way of doing what you want to do. You want PropertyOfBase to act as public in the context of MyType.MyMethod(), but to be protected in all other situations. Why?
A protected property is only accessible to an instance of a derived class, not to instances of derived classes.
There is a difference and it does make sense, protected members should not give up their value to any other instance, even an instance derived from the same type.
(Edited, got myself a bit tongue tied!)
As you are inheriting from MyBase, you can access all fields/properties/methods from it marked as "protected" using the "base" keyword.
public class MyBase
{
protected object PropertyOfBase { get; set; }
}
public class MyType : MyBase
{
void MyMethod()
{
object p = base.PropertyOfBase;
}
}
You can also declare MyType as a nested class of MyBase (instead of inheriting), this way you can access private/protected members when you send the class MyBase as a parameter
public class MyBase
{
protected object PropertyOfBase { get; set; }
public class MyType
{
public void MyMethod(MyBase parameter)
{
object p = parameter.PropertyOfBase;
}
}
}
To create an instance of MyType just use
var t = new MyBase.MyType();
t.MyMethod(new MyBase());

Categories