Hi i'm trying to implement a structure where by I need to be able to create an abstract method in an abstract class in C#, which has an abstract object as a parameter.. example-
public abstract class AbstractMapper
{
protected abstract AbstractObject doLoad(AbstractObject obj);
}
public abstract class UserMapper
{
protected override User doLoad(User obj)
{
}
}
In this example the "User" class extends the "AbstractObject" class... This is giving me errors on compile. Can someone advise on how i should achieve the above?
Use a generic type parameter on AbstractMapper constrained to be a subtype of AbstractObject:
public abstract class AbstractMapper<T> where T : AbstractObject
{
protected abstract T doLoad(T obj);
}
public class UserMapper : AbstractMapper<User>
{
protected override User doLoad(User obj)
{
...
}
}
UserMapper is extending Object class and you are trying to override a method that doens't exist (doLoad).
Also, the signature of the method has a return type of User and you are not returning anything.
If you want User class to extend AbstractObject class, then do this:
public class User : AbstractObject
{
protected AbstractObject doLoad(AbstractObject obj)
{
// do something here and return an instance of a class that extends Abstract object
return null; // added to make it compile
}
}
Do you know that the access modifier protected means that it is only visible inside the class and in child classes? Read this: https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
Related
I have a class that inherits an abstract class which inherits another abstract class. I can define the most-super class as being generic just fine, but I don't know how to define the middle class as being generic before I express the actual type I want in the final ListResults class.
internal abstract class LowerCommand<T> {
public abstract void Execute();
public abstract List<T> ExecuteList();
}
// currently gives error for `T`
internal abstract class HigherCommand : Lowercommand<T> {
// ... defines other stuff, nothing to do with
// already instantiated methods or T ...
}
class ListResults : HigherCommand<Results>
{
public override void Execute() {...}
public override List<Results> ExecuteList() {...}
}
Thanks for your help.
You still need to define the generic type parameter T on the definition of HigherCommand so it can in turn properly define LowerCommand.
internal abstract class LowerCommand<T> {
public abstract void Execute();
public abstract List<T> ExecuteList();
}
// Note that HigherCommand require a declaration of `T`
internal abstract class HigherCommand<T> : LowerCommand<T> {
// ... defines other stuff, nothing to do with
// already instantiated methods or T ...
}
class ListResults : HigherCommand<Results>
{
public override void Execute() {...}
public override List<Results> ExecuteList() {...}
}
Maybe this is a dumb question. But, I don't get the point what I am missing.
Given the following class-definition
public abstract class AbstractBaseClass
{
public abstract void Create(AnotherAbstractClass param1);
}
Wheras AnotherAbstractClass is defined
public abstract class AnotherAbstractClass
{
}
with a concrete implementation
public class AnotherConcreteImplementation : AnotherAbstractClass
{
}
I want to be able to have the override of the Create method to use a concrete type:
public class ConcreteImplementation : AbstractBaseClass
{
public override void Create(AnotherConcreteImplementation param1) <-- There is no suitable method for override
{
// param1 is an instance of the concrete implementation
}
public override void Create(AnotherAbstractClass param1) <-- this is working but I'll have to cast on each implementation
{
// param1 is an instance of the abstract class and needs a cast
}
}
Is this simply not possible or is there some way I'm not aware of? Maybe using generics?
Edit #1 (added more context)
I'm trying to achieve/enforce that in a concrete implementation there is only one parameter valid.
Think of it like it's a database-layer. The Create method will create a new entry in the database. As of each table has different values, the create-parameter also has.
The casting inside smells (in my opinion) as of it can be called with any concrete implementation of AnotherAbstractClass.
public class AddressTable : AbstractBaseClass
{
public override void Create(AnotherAbstractClass param1)
{
// cast to concrete instance
var casted = (ConcreteAddressCreate)param1;
}
}
public class CityTable : AbstractBaseClass
{
public override void Create(AnotherAbstractClass param1)
{
// cast to concrete instance
var casted = (ConcreteCityCreate)param1;
}
}
Having an instance of AddressTable I can call
addressIntance.Create(new ConcreteAddressCreate()); // would be okay
on the other hand I can call it
addressIntance.Create(new ConcreteCityCreate()); // would be okay but will fail at runtime with InvalidCastException
Edit #2 (additional info)
It should also be possible to extend the AbstractBaseClass class with more abstract methods later.
So, for me it's more likely to have generic methods instead of an concrete class-implemenation with 200 generic parameters for each method to implement.
It violates the Liskov Substitution Principle so it makes perfect sense you can't do this. Namely, you can't just "have" covariance like this for free:
AbstractBaseClass bcl = new ConcreteImplementation();
bcl.Create(new DifferentImplementationWithoutSecondAbstract());
The contract AbstractBaseClass defines makes Create have to work with any implementation of AbstractBaseClass passed in - if you give a constraint on what can be passed in you've violated the contract it defines.
Like you assumed - you can use generics:
// notice the recursive definition, we require the generic parameter
// to be a generic parameter of itself - allowing AbstractBaseClass
// to not be aware of its subclasses like in the other answers.
public abstract class AbstractBaseClass<T> where T : AbstractBaseClass<T>
{
public abstract void Create(T param1);
}
public class Concrete : AbstractBaseClass<Concrete>
{
public override void Create(Concrete param1)
{
Console.WriteLine("Hello!");
}
}
Yes, you can do that using generics:
public abstract class AbstractBaseClass<T>
where T : AnotherAbstractClass
{
public abstract void Create(T param1);
}
public class ConcreteImplementation : AbstractBaseClass<AnotherConcreteImplementation>
{
public override void Create(AnotherConcreteImplementation param1)
{
}
}
Generics is indeed the way to do it.
public abstract class AbstractBaseClass<TDerivedClass> where TDerivedClass : AnotherAbstractClass
{
public abstract void Create(TDerivedClass param1);
}
And then you can do:
public class ConcreteImplementation : AbstractBaseClass<AnotherConcreteImplementation>
{
public override void Create(AnotherConcreteImplementation param1) // Works because TDerivedClass = AnotherConcreteImplementation
{
...
}
}
I want to override an abstract method, but keep it abstract so derived classes are required to implement it themselves.
public abstract class ComponentController
{
public abstract void CreateCustomColumns();
}
public abstract class ClientComponentController : ComponentController
{
public override void CreateCustomColumns()
{
// All grids to do with clients should show these columns.
Grid.AddColumn("Client" ...
Grid.AddColumn("ClientLocation" ...
Grid.AddColumn("ClientPhoto" ...
}
}
public class ClientInvoicesComponentController : ClientComponentController
{
public override void CreateCustomColumns()
{
base.CreateCustomColumns();
// On top of the generic columns, I also want to show these.
Grid.AddColumn("InvoiceNumber" ...
Grid.AddColumn("InvoiceDate" ...
}
}
public class ClientCommunicationsComponentController : ClientComponentController
{
public override void CreateCustomColumns()
{
base.CreateCustomColumns();
// On top of the generic columns, I also want to show these.
Grid.AddColumn("CommunicationDate" ...
Grid.AddColumn("CommunicationType" ...
}
}
In this code, ClientInvoicesComponentController is not required to implement CreateCustomColumns() because this is not allowed:
public abstract class ClientComponentController : ComponentController
{
public abstract override void CreateCustomColumns()
{
Grid.AddColumn("Client" ...
Grid.AddColumn("ClientLocation" ...
Grid.AddColumn("ClientPhoto" ...
}
}
--> "Abstract method cannot declare a body"
So, how can I override CreateCustomColumns() in ClientComponentController, but still force it to be overridden again in derived classes like ClientInvoicesComponentController?
Of course it still CAN be overridden anyway, but there is nothing to indicate to the developer that it MUST be overridden... which is my aim.
-Brendan
In a word: Not.
A method being abstract means that it is declared but not defined. Being defined but abstract does not really make sense in this context, so it is not possible.
I would also very much like to know your use case. If there is some behaviour you want subclasses to inherit, but also add their own functionality, you could so something like this:
public abstract class BaseClass
{
public void DoSomething()
{
// Base class behaviour goes here.
DoSomethingInternal();
}
protected abstract void DoSomethingInternal();
}
public class SubClass : BaseClass
{
protected override void DoSomethingInternal()
{
// Sub class behaviour goes here.
}
}
In this case, I think it would be better to divide your logic into 2 methods, one method you play with and the other method your users play with. Assuming the "CreateCustomColumns" method is the name you want your users to override, you create another method, say "CreateCustomColumnsCore", for yourself. The classes may look like this:
public abstract class ComponentController
{
protected abstract void CreateCustomColumnsCore();
}
public abstract class ClientComponentController : ComponentController
{
protected override void CreateCustomColumnsCore()
{
// your code here
CreateCustomColumns(); // call users' implementation
}
public abstract void CreateCustomColumns();
}
public class ClientInvoicesComponentController: ClientComponentController
{
public override void CreateCustomColumns()
{
// user must implement this method.
}
}
Users can still override your CreateCustomColumnsCore method, this could be a feature or a bug based on if you can permit users to do this.
in my Silverlight 4 application I started creating and using some generics and now I stumbled upon the following problem:
In a non-generic class, I have a abstract method, that returns a generic class:
public abstract class DTO_Base()
{
public abstract ServiceModelBase<ServiceNodeBase> CreateBusinessObject();
}
The generic class is defined in the following way:
public abstract class ServiceModelBase<RootNodeType> where RootNodeType : ServiceNodeBase
Naturally, from DTO_Base derived classes will have to override the CreateBusinessObject method:
public class DTO_Editor : DTO_Base
{
public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
{
// the object to return have to be of type ServiceModelEditor
// which is derived from ServiceModelBase<ServiceNodeEditor>
// public class ServiceModelEditor : ServiceModelBase<ServiceNodeEditor>
// ServiceNodeEditor is derived from ServiceNodeBase
// public class ServiceNodeEditor : ServiceNodeBase
ServiceModelEditor target = new ServiceModelEditor()
...
Functions to populate the 'target'
...
return target;
}
}
The line return target; causes an error, stating that it isn't possible to implicitly convert the type ServiceModelEditor in ServiceModelBase<ServiceNodeBase>. Also, an explicit conversion via target as ServiceModelBase<ServiceNodeBase> doesn't work.
How would I have to implement this method to work?
Try this:
public interface IDTO<Node> where Node : ServiceNodeBase
{
ServiceModelBase<Node> CreateBusinessObject();
}
public abstract class DTO_Base<Model,Node> : IDTO<Node>
where Model : ServiceModelBase<Node>
where Node : ServiceNodeBase
{
public abstract Model CreateBusinessObject();
#region IDTO<Node> Members
ServiceModelBase<Node> IDTO<Node>.CreateBusinessObject()
{
return CreateBusinessObject();
}
#endregion
}
public class DTO_Editor : DTO_Base<ServiceModelEditor, ServiceNodeEditor>
{
public override ServiceModelEditor CreateBusinessObject()
{
// the object to return have to be of type ServiceModelEditor
// which is derived from ServiceModelBase<ServiceNodeEditor>
// public class ServiceModelEditor : ServiceModelBase<ServiceNodeEditor>
// ServiceNodeEditor is derived from ServiceNodeBase
// public class ServiceNodeEditor : ServiceNodeBase
ServiceModelEditor target = new ServiceModelEditor();
return target;
}
}
I have faced a similar problem before and the only thing reasonable to do is to make the core base class generic also. You can remove the Model generic parameter (and the interface) and it will look a little less scary, but you loose visibility on the functionality of ServiceModelEditor outside of the method.
As it is, you've got to return a ServiceModelBase<ServiceNodeBase>. One option is to make your base class generic:
public abstract class DtoBase<T> where T : RootNodeType
{
public abstract ServiceModelBase<T> CreateBusinessObject();
}
Then:
public class DtoEditor : DtoBase<ServiceNodeBase>
{
public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
{
...
}
}
If you are using .Net 4.0 I suggest you use interfaces to define your ServiceModelBase and specify an out variance modifier on that interface generic type:
class ServiceNodeBase { }
class ServiceNodeEditor : ServiceNodeBase {/*implementation*/}
//
interface IServiceModelBase<out RootNodeType>
where RootNodeType : ServiceNodeBase {
}
class ServiceModelEditor : IServiceModelBase<ServiceNodeEditor> {
/*implementation*/
}
//
abstract class DTO_Base {
public abstract IServiceModelBase<ServiceNodeBase> CreateBusinessObject();
}
class DTO_Editor : DTO_Base {
public override IServiceModelBase<ServiceNodeBase> CreateBusinessObject() {
return new ServiceModelEditor();
}
}
I have a c# Class that has lots of virtual methods, some of these methods are essentially abstract ( they are fully implemented in subclasses and the base class is empty).
To get it to compile i am throwing an InvalidOperationException in the base class with a comment on what should be done. This just feels dirty.
Is there a better way to design my classes?
edit:
It is for the middle tier of an application that will be ran in canada, half of the methods are generic hence the virtual. and half of the methods are province specific.
Public class PersonComponent()
{
public GetPersonById(Guid id) {
//Code to get person - same for all provinces
}
Public virtual DeletePerson(Guid id) {
//Common code
}
Public virtual UpdatePerson(Person p) {
throw new InvalidOperation("I wanna be abstract");
}
Public Class ABPersonComponent : PersonComponent
{
public override DeletePerson(Guid id)
{
//alberta specific delete code
}
public override UpdatePerson(Person p)
{
//alberta specific update codecode
}
}
hope this makes sense
Mark the base class as abstract, as well as the methods that have no implementation.
Like so
public abstract class BaseClass
{
public abstract void AbstractMethod();
}
public class SubClass: BaseClass
{
public override void AbstractMethod()
{
//Do Something
}
}
You can't have abstract methods outside of an abstract class. Marking a class as abstract means you won't be able to instantiate it. But then it doesn't make any sense to. What are you going to do with a class that doesn't implement the methods anyway?
Edit: From looking at your class, yeah I'd make PersonComponent abstract along with the UpdatePerson method. Either that, or if UpdatePerson just doesn't do anything for a PersonComponent keep it as is, but make the UpdatePerson method empty for PersonComponent.
Think about your object hierarchy. Do you want to share common code for all your derived classes, then implement base functionality in the base class.
When having shared base code, please notice the Template pattern. Use a public method and chain it to a protected virtual method with the core/shared implementation. End the shared implementation methodname with "Core".
For example:
public abstract class BaseClass
{
protected virtual void DeletePersonCore(Guid id)
{
//shared code
}
public void DeletePerson(Guid id)
{
//chain it to the core
DeletePersonCore(id);
}
}
public class DerivedClass : BaseClass
{
protected override void DeletePersonCore(Guid id)
{
//do some polymorphistic stuff
base.DeletePersonCore(id);
}
}
public class UsageClass
{
public void Delete()
{
DerivedClass dc = new DerivedClass();
dc.DeletePerson(Guid.NewGuid());
}
}