Armin,
How? Neither making the constructor in the derived class private, nor
friend, protected, or public would achieve this.
Public Class A
Private Class B : Inherits A
Public Sub New()
End Sub
End Class
Public Shared Function CreateInstance() As A
Return New B
End Function
End Class
The only way (IMO) is
- declare a public Interface within A
- declare the derived classes private within A ("Private Class..."). The
constructor is declared public.
- implement the public Interface in the derived classes
- Have the public function within A return objects implementing the public
Interface ("..As IMyInterface......Return New B").
Are you sure?
On the last item you need a public shared function, because A is an
Interface you cannot have shared functions. John's use of an abstract base
class (MustInherit Class) allows the Shared Function.
You are correct having the nested classes ensure that only A will be able to
create them, however you then run into a "source management issue"
Only a comment to Jay's suggestion: It might not be appliable in all
situations which means it is not a general solution for this design pattern.
Let's have classes A, B and C. Requirements:
- Only A can create B objects
- Only B can create C objects
You're changing the pattern! ;-) The pattern I was describing is 2 levels
(base & derived from base). You are describing N levels (base, derived from
base, derived from derived from base).
I was suggesting that:
- Only A can create B objects
- Only A can create C objects
- Only A can create D objects
- Only A can create E objects
Does fit nicely in a single assembly, especially when only that assembly can
create A objects! And referenced assemblies do not care about B, C, D, and
E. In other words A's sub new is only Friend not Protected.
Think of the case where you have an field in a database, and that field has
"behavior" in your code. A is the polymorphic class that represents the
field in the database, B, C, D, & E are the specific "values" that field can
have, each with their own specific behaviors. A.CreateInstance accepts the
database field and returns an instance of B, C, D or E. The assembly itself
represents the field as a whole.
Of course I agree, one size does not fit all.
IMHO what John "needs" is the C++ version of the Friend keyword, however
VB.NET does not support it. I don't believe the CLR supports it. Basically
in C++ Class B can state explicitly who is its Friends, then only those
specifically listed classes can use the method in B.
Hope this helps
Jay