c# inheritance help - c#

I am fairly new to inheritance and wanted to ask something. I have a base class that has lots of functionality that is shared by a number of derived classes.
The only difference for each derived class is a single method called Name. The functionality is the same for each derived class, but there is a need for the Name distinction.
I have a property in the base class called Name. How do I arrange it so that the derived classes can each override the base class property?
Thanks.

Declare your method as virtual
public class A
{
public virtual string Name(string name)
{
return name;
}
}
public class B : A
{
public override string Name(string name)
{
return base.Name(name); // calling A's method
}
}
public class C : A
{
public override string Name(string name)
{
return "1+1";
}
}

Use a virtual property:
class Base
{
public virtual string Foo
{
get;
set;
}
}
class Derived : Base
{
public override string Foo
{
get {
// Return something else...
}
set {
// Do something else...
}
}
}

You can declare it with a virtual or abstract keyword in the base class, then the derived class can over-ride it

you need to declare your property (in the base clase) as virtual

To enable each derived class to override the property you just need to mark the property as virtual
class Base {
public virtual Property1 {
get { ... }
set { ... }
}
}

Well I'm not sure from your description that inheritance is actually the right solution to the problem but here's how you make it possible for a property to be overridden:
class Base
{
public virtual string Name { get; set; }
}
But do you need it to be writable? A readonly property may make more sense in which case this might work:
class Base
{
public virtual string Name
{
get { return "BaseName"; }
}
}
class Derived : Base
{
public override string Name
{
get { return "Derived"; }
}
}

In the base class:
public virtual string Name { get; set; }
In the derived classes:
public override string Name { get; set; }
However, if the only difference between the classes is that they have different names, I'd argue that instead of inheritance you should just use the base class with the Name set in the constructor:
e.g.
public class MyObject
{
public string Name { get; private set; }
public enum ObjectType { TypeA, TypeB, ... }
public MyObject(ObjectType obType)
{
switch (obType)
{
case ObjectType.TypeA:
Name = "Type A";
// and so on
}
}
}

Related

How would one handle different return types when overriding abstract method

Say I have the following classes:
public abstract class A
{
protected abstract ReturnA Foo();
public void UseFoo()
{
var foo = Foo();
if (foo != null)
{
//logic here
}
}
}
public class B : A
{
protected override ReturnA Foo()
{
// Implementation specific code that returns ReturnB instead.
}
}
public class C : A
{
protected override ReturnA Foo()
{
// Implementation specific code that returns ReturnC instead.
}
}
public class ReturnA
{
public int Id { get; set; }
public string Address { get; set; }
}
public class ReturnB
{
public string Id { get; set; }
public string PhoneNumber { get; set; }
}
public class ReturnC
{
public Guid Id { get; set; }
public string Name { get; set; }
}
I know that C# does not support derived return types, but this is not what I need either.
Classes B and C are implementation specific and therefore their return types have nothing to do with eachother.
The reason why I would want to handle this, is because the method UseFoo in class A may have some generic checks and other generic logic, that has nothing to do with the returned object itself.
So I want to "outsource" only the code that is implementation specific and not have to instead make UseFoo abstract and have every implementation write the same generic code.
Is there any way to solve this at all?
EDIT: Neither ReturnC nor ReturnB are derived from ReturnA. Updated with examples.

Derive Abstact Property

I have a base class that has an abstract property:
public class BottomClass {
public abstract string Name {get;set;}
}
I now have a class that derives from that:
public class MiddleClass:BottomClass {
public override string Name {get;set;}
}
what I now want is that the "MiddleClass" itself defines that property as abstract so that a class deriving from that will be forced to implement the property. The following code is not working that way:
public class MiddleClass:BottomClass {
public abstract override string Name {get;set;} // Not possible that way
}
public class TopClass:MiddleClass {
public override string Name {get;set;} ="tothetop";
}
Is there a way to achieve what I want?
If you define a property as abstract, you have to implement it in some non abstract class. So the only possible way to have the property in both classes is
public abstract class BottomClass
{
public abstract string NameB { get; set; }
}
public abstract class MiddleClass : BottomClass
{
public abstract string NameM { get; set; }
}
public class TopClass : MiddleClass {
public override string NameB { get; set; }
public override string NameM { get; set; }
}
As far as I can understand, your intention is to have 'Name' property in MiddleClass.
Or don't implement it, as Damien commented above.
Throw exceptions if you have some reason not to make the class abstract.
public class MiddleClass:BottomClass
{
public override string Name
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
}

Deriving properties?

Is there a way of declaring derived properties?
public class Vehicle {
public VehicleType Type { get; set; }
}
public class Car : Vehicle {
public CarType Type { get; set; }
}
public class VehicleType {}
public class CarType : VehicleType {}
so that when I call Car.Type; I only see car types?
You can't do that. The Type property has to have the same type in both the base and the derived classes.
One way of doing this is using generics:
public class Vehicle<TVehicleType> where TVehicleType: VehicleType {
public TVehicleType Type { get; set; }
}
public class Car : Vehicle<CarType> { }
Car car = new Car();
car.Type = new CarType();
Properties can indeed be declared abstract or virtual on a base class and overridden by a derived class. But when using inheritance, you cannot change the input parameters or return type of the function/property.
If you find that you want a totally different type for the same property between the derived and the base, you may have a design smell. Perhaps inheritance isn't what you actually want.
If you still think you need something like this, you might be able to leverage generics:
class Base<T>
{
public virtual T MyProp { /* ... */ }
}
// Derived class that uses string for prop
class Derived1 : Base<string>
{
public override string MyProp { /* ... */ }
}
// Derived class that uses int for prop
class Derived2 : Base<int>
{
public override int MyProp { /* ... */ }
}
Something like this should work:
public class Car : Vehicle {
public CarType Type
{
get { return base.Type; }
set { base.Type = value; }
}
}
I would suggest not using the name "Type" because it's a reserved member already.

Struggling to implement abstract property in derived class

This all got a little trickier than I had intended. I'm using the HistoricalReportWrapper class because I retrieve my data through an API which has made it not realistic to have HistoricalReport implement IReport directly.
public abstract class CormantChart : Chart
{
public abstract IReport Report { get; protected set; }
}
public abstract class HistoricalChart : CormantChart
{
public override HistoricalReportWrapper Report { get; protected set; }
public HistoricalChart(HistoricalChartData chartData) : base(chartData)
{
Report = GetHistoricalReport(chartData.ReportID);
}
protected HistoricalReportWrapper GetHistoricalReport(int reportID)
{
return SessionRepository.Instance.HistoricalReports.Find(historicalReport => int.Equals(historicalReport.ID, reportID));
}
}
public class HistoricalReportWrapper : IReport
{
public HistoricalReport inner;
public int ID
{
get { return inner.ID; }
set { inner.ID = value; }
}
public string Name
{
get { return inner.Name; }
set { inner.Name = value; }
}
public HistoricalReportWrapper(HistoricalReport obj)
{
inner = obj;
}
}
public interface IReport
{
string Name { get; set; }
int ID { get; set; }
}
The idea here is that when I am working inside of the HistoricalChart class I need to be able to access specific properties of the HistoricalReport. The rest of my program, however, only needs to have access to the HistoricalReport's ID and Name. As such, I would like to expose IReport's properties to the world, but then keep the details contained to the class.
As it stands, all the classes which inherit HistoricalChart generate a "does not implement inherited abstract member" as well as a warning on HistoricalChart indicating that I am hiding CormantChart's Report.
What's the proper way to declare this to achieve what I'd like?
Thanks
EDIT: Whoops, I missed an override. Now, when I try to override CormantChart Report I receive:
'CableSolve.Web.Dashboard.Charting.Historical_Charts.HistoricalChart.Report': type must be 'CableSolve.Web.Dashboard.IReport' to match overridden member 'CableSolve.Web.Dashboard.Charting.CormantChart.Report' C
EDIT2: Taking a look at C#: Overriding return types might be what I need.
Because
public HistoricalReportWrapper Report { get; protected set; }
is not an implementation of
public abstract IReport Report { get; protected set; }

Do inheritance right

I have class:
internal class Stage
{
public long StageId { get; set; }
public string StageName { get; set; }
public int? Order { get; set; }
public Stage()
{
Order = 0;
}
}
I have also:
public class GroupStage : Stage
{
private override long StageId { set { StageId = value; } }
public GroupStage() : base() { }
public void InsertStage(long groupId)
{
}
public static void SetStageOrder(long stageId, int order)
{
....
}
public static void DeleteStage(long stageId)
{
....
}
public static GroupStage[] GetStages(long groupId)
{
....
}
}
and:
public class TaskStage : Stage
{
public DateTime? Time { get; set; }
public TaskStage()
: base()
{
....
}
public static Stage GetNextTaskStage(Guid companyId, long taskId)
{
....
}
public static Stage[] GetTaskStages(Guid companyId, long taskId)
{
....
}
}
This is not working and I get the exception:
Inconsistent accessibility: base class Stage is less accessible than class GroupStage
I want Stage class to be private and without access except to GroupStage and TaskStage. I also want to make StageId be private in GroupStage and in TaskStage.
How can I do that without duplicate the members of Stage in GroupStage and in TaskStage?
You can't make a derived class more accessible than it's base class. What you can do is make TaskStage and GroupStage internal as well, then inherit and expose public interfaces so that only the interface is visible outside of your assembly.
public interface IGroupStage
{
public string StageName{ get; set; }
...
}
interal class GroupStage : IGroupStage
{
...
}
You need to make you Stage class public or protected. if you make it abstract it cant be instantiated on that level, so if its public you dont have to worry about it being created as a base class
Make it protected instead of private. If you make it protected, you let classes that inherit from it call methods on the base class, and inherit the base class members.
What you probably actually want is for Stage to be an abstract base class which, therefore, cannot directly be instantiated regardless of its accessibility modifier. Change your definition of Stage:
public abstract class Stage
{
protected long StageId { get; set; }
public string StageName { get; set; }
public int? Order { get; set; }
protected Stage()
{
Order = 0;
}
}
The protected modifier means that your derived classes will be able to access that member, but it will not be accessible outside those classes.

Categories