Re: a sort of multiple inheritance

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Harlan Messinger wrote:
John Rivers wrote:
Thanks for the reply

This technique seems very powerful

But I can't find a way to limit instanciation of the nested class to
the parent class:

public class A {
B b = new B(); // won't compile
public class B {
protected B() {
}
}
}

there doesn't seem to be any parent-specific access rights

I want to hand out references to the nested class as a sort of proxy
to the parent class

I found a couple of interesting approaches (along with a couple that fall short by suggesting the use of *internal*) here:

http://stackoverflow.com/questions/1664793/how-to-restrict-access-to-nested-class-member-to-enclosing-class

Note that that question really isn't exactly the same as the OP here. Specifically, if we assume a particular solution to the question in the OP, then yes...the above question is appropriate, because it answers a question about the implementation detail (and of course in the same way I replied earlier).

But it doesn't really get at what might be a more significant issue, related to the specific question in the OP.

Two people suggest creating a public interface for B to implement and then making B private. Another came up with a method that I don't quite understand yet that involves a static initialization block and a lambda expression.

The lambda-based solution is difficult to understand because the person who wrote it failed to provide all of the details, and the details he did provide aren't actually quite right.

What that code is doing is creating a delegate representing a factory method that can instantiate the class with the private constructor, and storing a reference to that in the outer class where the Journal class can get at it, but no other code can.

That way, the nested class can be public (so any code can see the type and use public members of the type), but the constructor itself is private, preventing ANY class from simply instantiating the type directly (even the outer class). The outer class can instantiate only by going through the factory method, and it's the only class that can see the factory method.

It takes advantage of the fact that the nested class can access private members of the outer class, and in doing so inverts the usual relationship between the classes with respect to method visibility. This would probably have been more obvious if the person had shown the outer class actually _using_ the delegate. It's left to the reader to infer that usage.

It's a reasonably clever solution, but does have its own problems: that a) the interface implemented by the nested class is tied to the class itself, and b) every constructor in the nested class needs a corresponding factory method delegate to go with it, and a delegate type variable in the outer class to store the delegate. It also has the particularly egregious flaw that it's dependent on the order in which the code executes, and what types are accessed.

In particular, the static initializer shown (which has the wrong syntax, by the way...the code as shown won't even compile) isn't going to execute until the inner type is actually accessed somehow. If you just try to get an instance of the inner class from the outer class without doing something to force the inner class to run its static initializer, then the factory method delegate is never created and so can't be invoked.

This can be addressed by providing a dummy method in the inner class to force the initialization. But then you've got this useless dummy method in the inner class that necessarily is public and so visible to everyone for no good reason.

I prefer the interface approach because it specifically avoids all of the above problems. :) But, if you're curious, I've copied a complete code example below that I wrote showing exactly how the factory delegate approach works.

Pete


using System;

namespace TestPublicFactoryNestedClass
{
class Outer
{
public class Inner
{
static Inner()
{
_funcInnerFactory = delegate { return new Inner(); };
}

public static void InitType() { }

private Inner()
{
}
}

private static Func<Inner> _funcInnerFactory;

public static Inner CreateInner()
{
// Must be called to ensure that _funcInnerFactory is
// initialized!
if (_funcInnerFactory == null)
{
Inner.InitType();
}

return _funcInnerFactory();
}
}

class Program
{
static void Main(string[] args)
{
Outer.Inner inner = Outer.CreateInner();
}
}
}
.



Relevant Pages

  • Re: why do we need "static" inner classes??
    ... I am a newbie in java and have prior OO experience in PB and .Net. ... Why do some other OO languages prevent implementation inheritance? ... have an instance of the nested class to access that field. ... There's no such thing as a "static inner" class in Java. ...
    (comp.lang.java.programmer)
  • Re: static inner classes
    ... Inner classes cannot be static. ... A nested class that is declared static is *not* an inner class. ...
    (comp.lang.java.programmer)
  • Re: Nested classes
    ... The inner class is a whole own thing. ... my inner class is declared in the private section of Outer of course. ... The nested class is not even visible to the public, ... What's am I gaining with declaring ...
    (comp.lang.cpp)