Deriving properties? - c#

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.

Related

Generics: cast derived class back to it's parent super class

I have three base classes:
public class ItemBase
{
public string Name { get; set; }
}
public class ProductBase<T> : ItemBase
where T : ItemBase
{
public List<T> Modifiers { get; set; }
public List<T> GroupModifiers { get; set; }
}
public class ModifierBase<T> : ItemBase
where T : ItemBase
{
public List<T> ChildModifiers { get; set; }
}
And two derived classes:
public class Product : ProductBase<Modifier>
{
public string Some_Product_Specific_Property { get; set; }
}
public class Modifier : ModifierBase<Modifier>
{
public string Some_Modifier_Specific_Property { get; set; }
}
The intent behind all this is to have different sets of derived classes like Product and ProductFromOtherSystem each with it's own specific properties but with the same basic properties.
And now I need to process basic properties of any class derived from ProductBase<T>.
For this purpose I want to use something like this:
public static void DoSomething(ProductBase<ModifierBase<ItemBase>> item)
{
Console.WriteLine(item.Name);
}
The issue here is that I cannot pass parameters to it:
Product product1 = new Product();
DoSomething(product1);
ProductFromOtherSystem product2 = new ProductFromOtherSystem();
DoSomething(product2 as ProductBase<ModifierBase<ItemBase>>);
The error is like
Cannot convert type _ to _ via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion
I've tried to downcast it somehow but have not found any solution. I wonder if it is possible to do it?

Declare a property of abstract class type

I have an abstract class:
public abstract class BaseClass<T> { ... }
I have some inheriting classes:
public Class1<T>: BaseClass<T> { ... }
public Class2<T>: BaseClass<T> { ... }
I would like to define a property to hold my inheriting class, how can I do that?
public class API{
public BaseClass<T> MyClass { get; set; }
}
I would like to call it like this:
new API { MyClass = new Class1<MyT> };
Your method would not work because the API class does not have a generic type and still uses 'T' which has not been defined.
You can correct your problem by using any of the following
public class API{
public BaseClass<MyT> MyClass { get; set; }
}
or
public class API<T> {
public BaseClass<T> MyClass { get; set; }
}
new API<MyT> { MyClass = new Class1<MyT>() };
In case you want to check the type which you shouldn't need to, you can use the is keyword.
obj **is** Class2<T>
For example
if (obj is Class2<MyT>)
{
// Do whatever is it that you want with the object.
// If you want to use the object as Class2, you can simply cast it
// to Class2 by using
((Class2<MyT>)obj).methodForOnlyClass2();
}

In a derived class, how to have a property of a derived type from the type of the property in the base class?

This is a huge design problem that I often encounter and I think it is because I don't understand OOP right.
Here is the class of the base Property :
public class BasePropety {}
Here is the type of my DerivedProperty:
public class DerivedProperty : BaseProperty
{
public AClass A { get; set; }
}
Here is my base class :
public class BaseClass
{
public BaseProperty Property { get; set; }
}
Here my derived class :
public class DerivedClass : BaseClass
{
public DerivedProperty Property { get; set; }
public void MethodExample()
{
AClass aValue = this.Property.A;
}
}
I could of course typecast my property but it is annoying:
public class DerivedClass : BaseClass
{
public void MethodExample()
{
var typedProperty = (DerivedProperty) this.Property;
AClass aValue = typedProperty.A;
}
}
I know I can use the new keyword but I read here and there that it is a bad practice, so how I am suppose to achieve this ? Should I create a new property ?
Thanks in advance for your answers.
Sounds like you need generics instead:
public class BaseClass<T> where T : BaseProperty
{
public T Property { get; set; }
}
public class DerivedClass : BaseClass<DerivedProperty>
{
public void MethodExample()
{
AClass aValue = Property.A;
}
}
Note that this means there's only one property - whereas in your current code, you actually have two independent properties, which happen to have the same name. I suspect you don't want that.

Dynamic instance of c# list with inherited type

Case 1:
I have the following case: I want to apply dynamic polymorphism to a List.
I have a base class ALayer
public class ALayer {
int Id {get; set;}
}
And another base class A that contains a list of layers
public class A {
List<ALayer> Layers {get; set;}
}
Then I will have several classes that extends from my base classes:
public class BLayer: Alayer {
int blayerattr {get; set;}
}
public class B:A {
//I want to apply the polymorphism in the constructor
public B(){
this.Layers = new List<BLayer>();//error
}
}
public class CLayer: Alayer {
int clayerattr {get; set;}
}
public class C:A {
//I want to apply the polymorphism in the constructor
public C(){
this.Layers = new List<CLayer>();//error
}
}
but the compiler gives me an error of not being able to implicitly cast the Child Layer into the Parent Layer. The child layers are quite different so I decided to create the ALayer Parent Class.
is it possible to code this? or do I have a flaw in my design? or how do I instance my list depending on the type of class?
Thank you in advance!
Edited Question
Case 2:
Following the last case, how do I apply this Generics to a middle class in the inheritance? let's say there exists a Middle class between A and B
public class Middle:A{
int anyatrr;
}
and then my class B inherits from Middle, but still in the B constructor is where I want to apply the dynamic polymorphism.
public class B:Middle {
public B(){
this.Layers = new List<BLayer>();
}
}
How can I combine in the Middle class the Generics notation plus the inheritance from the class A
You can use Generics:
public abstract class ALayer
{
int Id { get; set; }
}
public abstract class A<T> where T : ALayer
{
protected List<T> Layers { get; set; }
}
public class B : A<BLayer>
{
//I want to apply the polymorphism in the constructor
public B()
{
this.Layers = new List<BLayer>();
}
}
public class BLayer : ALayer
{
int blayerattr { get; set; }
}
You can get a lot more information on C# generics here: https://msdn.microsoft.com/en-us/library/512aeb7t.aspx
Update
Case 2
(Credits to X.L.Ant)
Just do :
public class Middle<T> : A<T>{ and then public class B : Middle<BLayer> {

c# inheritance help

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
}
}
}

Categories