Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't my public class extend an internal class?

I really don't get it.

If the base class is abstract and only intended to be used to provide common functionality to public subclasses defined in the assembly, why shouldn't it be declared internal?

I don't want the abstract class to be visible to code outside the assembly. I don't want external code to know about it.

like image 470
David Avatar asked Sep 02 '10 12:09

David


People also ask

Can internal class have public members?

Class, record, and struct member accessibility However, a public member of an internal class might be accessible from outside the assembly if the member implements interface methods or overrides virtual methods that are defined in a public base class.

Can internal class be inherited in C#?

Solution 1 Your base class can't be less accessible then your derived class. So you can't inherit a internal class to a public class.

Can you extend nested class?

You can easily extend nested static classes You can, but the inner class has to be static, because if it's not, then every instance of the inner class has a reference to the enclosing instance of the outer class. A static nested class doesn't have that reference, and you can extend it freely.


5 Answers

UPDATE: This question was the subject of my blog on November 13th of 2012. See it for some more thoughts on this issue. Thanks for the great question!


You're right; it doesn't have to be that way. Other OO languages allow "private inheritance", whereby the fact that D inherits from B can only be taken advantage of by code that has the ability to see B.

This was a design decision of the original C# designers. Unfortunately I am away from my desk right now - I'm taking a couple of days off for the long weekend - so I don't have the language design notes from 1999 in front of me. If I think of it when I get back I'll browse them and see if there is a justification for this decision.

My personal opinion is that inheritance should be used to represent "is a kind of" relationships; that is, inheritance should represent the semantics of the domain being modelled in the language. I try to avoid situations where inheritance is used as a code sharing mechanism. As others have mentioned, it's probably best to prefer composition to inheritance if what you want to represent is "this class shares implementation mechanisms with other classes".

like image 74
Eric Lippert Avatar answered Sep 29 '22 09:09

Eric Lippert


By inheriting from a class, you expose the functionality of the base class through your child.

Since the child class has higher visibility than its parent, you would be exposing members that would otherwise be protected.

You can't violate the protection level of the parent class by implementing a child with higher visibility.

If the base class is really meant to be used by public child classes, then you need to make the parent public as well.

The other option is to keep your "parent" internal, make it non-abstract, and use it to compose your child classes, and use an Interface to force classes to implement the functionality:

public interface ISomething
{
    void HelloWorld();
}

internal class OldParent : ISomething
{
    public void HelloWorld(){ Console.WriteLine("Hello World!"); }
}

public class OldChild : ISomething
{
    OldParent _oldParent = new OldParent();

    public void HelloWorld() { _oldParent.HelloWorld(); }
}
like image 37
Justin Niessner Avatar answered Oct 03 '22 09:10

Justin Niessner


I think the closest thing you can do is prevent other assemblies creating the abstract class by making its constructor internal, to quote from MSDN:

An internal constructor prevents the abstract class from being used as the base class of types that are not in the same assembly as the abstract class.

You can then try adding an EditorBrowsableAttribute to the class to try and hide it from IntelliSense (though, I've had mixed results using it to be honest) or put the base class in a nested namespace, such as MyLibrary.Internals to seperate it from the rest of your classes.

like image 41
Samuel Avatar answered Oct 02 '22 09:10

Samuel


I think you're mixing concerns here, and C# is to blame, actually (and Java before it).

Inheritance should serve as a categorization mechanism, whereas it's often used for code reuse.

For code reuse it's always been known that composition beats inheritance. The problem with C# is that it gives us such an easy way to inherit:

class MyClass : MyReusedClass { }

But in order to compose, we need to do it by ourselves:

class MyClass {
  MyReusedClass _reused;
  // need to expose all the methods from MyReusedClass and delegate to _reused
}

What's missing is a construct like a trait (pdf), which will bring composition to the same usability level as inheritance.

There's research about traits in C# (pdf), and it would look something like this:

class MyClass {
  uses { MyTrait; }
}

Although I'd like to see another model (that of Perl 6 roles).

UPDATE:

As a side note, the Oxygene language has a feature that lets you delegate all members of an interface to a member property that implements that interface:

type
  MyClass = class(IReusable)
  private
    property Reused : IReusable := new MyReusedClass(); readonly;
      implements public IReusable;
  end;

Here, all interface members of IReusable will be exposed through MyClass and they'll all delegate to the Reused property. There are some problems with this approach, though.

ANOTHER UPDATE:

I've begun implementing this automatic composition concept in C#: take a look at NRoles.

like image 29
Jordão Avatar answered Oct 02 '22 09:10

Jordão


I think this would violate the Liskov Substitution Principle.

In cases like this, I have used internal classes and prefer composition over inheritance. Is there anything about your design that prohibits containing all such functionality in your internal class, and then have your public classes contain an instance of this internal class?

like image 27
Dave Avatar answered Oct 02 '22 09:10

Dave