Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent an abstract class with public derived classes from being inherited in other assemblies?

I want to write something like the following:

    internal class InternalData
    {
    }

    public class PublicData
    {
    }

    abstract internal class Base {
        internal Base() { }

        private static InternalData CreateInternalDataFromPublicData(PublicData publicData)
        {
            throw new NotImplementedException();
        }

        abstract protected void DoProcess(InternalData internalData);

        public void Process(PublicData publicData)
        {
            InternalData internalData = CreateInternalDataFromPublicData(publicData);
            DoProcess(internalData);
        }
    }

    public sealed class Derived : Base
    {
        protected override void DoProcess(InternalData internalData)
        {
            throw new NotImplementedException();
        }
    }

That is, Base contains some internal logic and is not intended to be inherited by classes outside of my assembly; and Derived is accessible from the outside. InternalData also contains some internal logic and, as it would (and should) never be used from the outside, i also want to make it internal.

Of course the code above won't compile as the Base should not be less accessible than Derived. I can set the Base to be public, that's fine, but it leads to another problem. If Base is public, then there could possibly be some ExternalDerived : Base in some other assembly. But Base.DoProcess accepts an InternalData as its argument, so that ExternalDerived cannot implement it (as it doesn't know about the InternalData). Internal parameterless Base constructor prevents creation of any ExternalDerived instances, and thus nobody will implement ExternalDerived.DoProcess and no InternalData public exposure is needed, but the compiler doesn't know it.

How can i rewrite the code above so that there will be an abstract DoProcess(InternalData) method and so that InternalData class will be internal?

like image 351
penartur Avatar asked Feb 22 '12 10:02

penartur


People also ask

How can you prevent a class from being inherited by another class?

You can prevent a class from being subclassed by using the final keyword in the class's declaration. Similarly, you can prevent a method from being overridden by subclasses by declaring it as a final method. An abstract class can only be subclassed; it cannot be instantiated.

Is it possible that an abstract class is inherited by another class?

An abstract class cannot be inherited by structures.

Do derived classes inherit members?

The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class.

How can we define derived classes in the context of inheritance?

– Derived class. • Class that inherits data members and member functions from a. previously defined base class. – Single inheritance.


1 Answers

To make InternalData internal, DoProcess must be private or internal (or InternalAndProtected, but C# doesn't support this CLR feature). It can't be protected or protected internal.

internal abstract DoProcess(InternalData internalData);

I'd probably also add an internal abstract void DoNotInheritFromThisClassInAnOutsideAssembly() member. That prevents anybody outside the assembly from inheriting from your class, because they can't implement that member and they get a reasonable compiler error. But you can't make the Base class itself internal.


I'd consider refactoring the code, so that you have no common base class. Probably by using some internal interfaces and composition.

like image 133
CodesInChaos Avatar answered Nov 15 '22 19:11

CodesInChaos