3

Context

I have an scenario in which I wish to define several Bar classes, each of which must define Request, Response and Error classes of their own. For this reason, I have written an abstract Foo class, within an intension to force an the implementation.

Request, Response and Error share a base class, PDU, and must implement their respective interfaces. Each Bar requires a sufficiently unique Request, Response and Error, that they must be independently defined.

Furthermore, the Request, Response and Error of each Bar shall not be instantiated outside of that Bar, so it seems correct (at least to me) that the class definitions should be nested.

Question

Is it possible to override a nested class definition within a child, inheriting from an abstract parent? Or at least to achieve the same through another approach?

Illegal Example

Below is an illegal code example of how I would of liked to write it:

public abstract class Foo
{
    public class Request: PDU, IRequest
    { }

    public class Response : PDU, IResponse
    { }

    public class Error : PDU, IException
    { }
}

public class Bar : Foo
{
    public override Request
    {
        // Definition of Request goes here
    }

    public override Response
    {
        // Definition of Response goes here
    }

    public override Error
    {
        // Definition of Error goes here
    }
}
George Kerwood
  • 1,248
  • 8
  • 19
  • Nested classes hierarchy? Why don't use separate assemblies and internal classes? – Dennis Dec 11 '20 at 10:19
  • 3
    Sounds more like you want to expose an interface rather than override nested classes. – DavidG Dec 11 '20 at 10:23
  • why do you care for the names of the classes that implement your interface? Just pass an instance of `PDU` to whatever BL needs the request, error or response. You seem to have overcomplicated your problem, just omit all this nasty nested classes and re-think from scratch: what are your actual classes and what dependencies do they have? – MakePeaceGreatAgain Dec 11 '20 at 10:25
  • @Dennis I guess I was following advise of uses nested classes "when the enclosed class is only useful to the enclosing class" and there may be (I'm yet to be certain) scenarios in which the nested class may need access to private members of the enclosing class. Granted this might be the wrong approach and your traditional recommendation might be better suited. – George Kerwood Dec 11 '20 at 10:26
  • How do you want to use those classes? A scenario of that would help much. Please elaborate on what you want to **achieve**, not on what you think may be the solution. – MakePeaceGreatAgain Dec 11 '20 at 10:29
  • Nesting a class within another one does not really restrict its access - it´s more like another namespace. Everything public within a nested class is also accessable to the outside, just via the outer class-name. So you can also access `Foo.Request` from within `Bar`. – MakePeaceGreatAgain Dec 11 '20 at 10:32
  • @HimBromBeere I'm questioning the approach myself. Your comment comparing it to another namespace was perhaps my primary motivation. Each `Request`, `Response` and `Error` variant is uniquely useful to its `Bar`. I was experimenting with the approach mostly for "structural" reasons over function. – George Kerwood Dec 11 '20 at 10:37

2 Answers2

4

It isn't possible to override a nested class, so your current approach won't work. However, I think this is what you are trying to achieve.

My advice would be to use interfaces and generics. So let's say you have your 3 interfaces:

public interface IRequest
{
    //snip
}
public interface IResponse
{
    //snip
}

public interface IException
{
    //snip
}

Now you can make your base class look like this:

public abstract class BaseThing<TRequest, TResponse, TError>
    where TRequest : IRequest
    where TResponse : IResponse
    where TError : IException
{
    // An example method
    public abstract TResponse GetThing(TRequest request);
}

Now you can make some concrete definitions of the above things:

public class FooRequest : IRequest
{
    //snip
}

public class FooResponse : IResponse
{
    //snip
}

public class FooError : IException
{
    //snip
}

public class FooThing : BaseThing<FooRequest, FooResponse, FooError>
{
    public override FooResponse GetThing(FooRequest request)
    {
        //snip
    }
}
DavidG
  • 113,891
  • 12
  • 217
  • 223
  • This is exactly what I need in place of my approach, thank you kindly. My reasoning was primarily for containment and structure more than function. I should be able to achieve the same through access modifiers and namespacing. – George Kerwood Dec 11 '20 at 10:40
1

Since the classes Request, Response and Exception are very specific to each Bar class, it does not look like the case for a 'class'. All you need is the interfaces IRequest, IResponse, IException.

Implement these interfaces in each 'Bar' class and provide class specific implementation for the methods in the interface. This way there is no issue for derived classes, regular inheritance principles will work.

What remains is the question of inheriting from PDU class - Does the PDU class contain any implementation? Or is it an abstract class? If it does not have any implementation, it can be converted into an interface which can be implemented by Bar classes.

If it contains implementation, each Bar class can create an instance of PDU class for use by the methods implementing IRequest/IResponse/IException.

samiksc
  • 167
  • 10