0

So I looked through many related questions and none of them seem to fit all the way. At least not in my current understanding. As this is a simple issue, I'm going to be concise with my question and code.

I have five classes:

internal class A
internal abstract class B : A
internal abstract class C : B
public class D : C
public class E {
    public void X(C c) { }
}

There is an obvious accessibility issue here with the parameter C being used in a public method. I need to access class D without exposing class C. I believe this may be due to the nature of the abstract keyword, and my minimal experience with using it.

To date I have never had a known need to create an abstract class, and this is my first time dealing with it on this level. From my understanding, it isn't really necessary in this case to use abstract classes so long as I remember to implement everything properly.


My Questions

  • Should I create a class F that has a private instance of D as a sort of wrapper to prevent exposure?
  • What is a solid reason to use abstract as I don't believe this code is a good example of it.
  • What are other ways I can expose D without exposing A, B, or C?

Notes

  • I am trying to be surgical with my current changes.
  • Originally all classes were private.

I've looked at many related posts (here are a few of them):

Hazel へいぜる
  • 2,751
  • 1
  • 12
  • 44
  • 2
    I am not sure what the mystery is here. You are creating a `public` class and having it derive from an `internal` one. This has nothing to do with the `abstract` keyword. You are trying to do something that doesn't make sense. Think of it this way: You are telling the compiler you want caramel-based candy but the candy cannot contain caramel. – JuanR Oct 16 '18 at 19:33
  • @JuanR Thank you for pointing out the error in my logic there; it has been a long day fighting with this code and my mind is beginning to melt around it. I've clarified the post. – Hazel へいぜる Oct 16 '18 at 19:39
  • No worries. Why is it that you don't want to expose `A`, `B` or `C`? If you don't want to expose them, why is `D` deriving from them? – JuanR Oct 16 '18 at 19:43
  • @JuanR `A`, `B`, and `C` are used by multiple classes (and can be), but the code is transitioning to an API of sorts and no subscribers should have access to those classes. The idea is to make the API as simplistic as possible, and not expose the tools used in the background. `D` requires them currently due to specific methods such as custom disposals, etc. All of the code was written a couple decades ago and is currently focused on a singular task; my current task is to refactor it to be more simplistic and reusable (only the simplistic things should be reusable). – Hazel へいぜる Oct 16 '18 at 19:45
  • The `abstract` keyword indicates you have a base class (or abstraction) of what an object is, but not necessarily all of the details. The concrete (deriving) class then becomes the actual implementation. Some properties or methods might be shared by all deriving classes so those can live in the base class. – JuanR Oct 16 '18 at 19:47
  • I understand better now. One way of going about it is to hide them behind an interface. – JuanR Oct 16 '18 at 19:47
  • "What is a solid reason to use `abstract`" - basically, `abstract` is all about providing details and parts, or setting up a contract-like situation that says all the descendants from here on down get these things already implemented for them. You set up a partial implementation (which could just be method signatures, but then you could just use an interface) that sets up things for the children classes, but recognizes that **all** the children are going to have some differences in other areas, some things in their implementation which are unique. –  Oct 16 '18 at 19:48
  • @JuanR Is there any way you can demonstrate this? From my understanding I would be converting the `abstract` classes to `interfaces` which just contain the signatures? Thus allowing them to be `internal`. – Hazel へいぜる Oct 16 '18 at 19:50
  • @AgapwIesu Thank you for the definition, but I'm really wanting a useful example that I may be able to look for. There are a lot of things that don't seem to add up about this old code and it may just be an old habit the previous developer had. – Hazel へいぜる Oct 16 '18 at 19:52
  • Let me ask you this, is D the only thing that ever derives from C? –  Oct 16 '18 at 19:55
  • @AgapwIesu That is correct. – Hazel へいぜる Oct 16 '18 at 20:23

1 Answers1

2

You can use interfaces to hide the details. Consider this:

//This represents the contract, regardless of the underlying object
public interface ISomeObject
{

}

//Class is internal, but implements the interface
internal class A : ISomeObject { }
internal abstract class B : A { }
internal abstract class C : B { }

//Class D is still internal
internal class D : C { }

public class E
{   
    //Method uses interface, which is public     
    public void X(ISomeObject c) { }

    public ISomeObject DoSomething()
    {
        //Create internal class, return it for use (as a contract)
        return new D();
    }
}

Sample usage:

var e = new E();
var result = e.DoSomething();
e.X(result);

This works because from an external point of view, you are dealing with a public contract, not the actual implementation.

JuanR
  • 7,405
  • 1
  • 19
  • 30