a sort of multiple inheritance

J

John Rivers

by implementing abstract classes as nested classes

the implementation has full access (via a reference) to all the
members of the parent class

this means I can merge the functionality of multiple classes and treat
one class as any other class

with full type safety

it also makes bidirectional control quite simple and manageable also
Freak can call methods on FreakAsX and Y and vice versa

this seems the cleanest way to achieve this - using interfaces for
bidirectional control is quite messy

I am no expert in OO so what I want to know is: is this a well known
technique and how would you achieve
similar results otherwise, or would you "dumb down" the Freak and use
a controlling class defined seperately to both Freak and X, Y ?


class Freak : Person {
class FreakAsX : X {
Freak Base;
public FreakAsX(Freak Base) {
this.Base = Base;
}
}
class FreakAsY : Y {
Freak Base;
public FreakAsY(Freak Base) {
this.Base = Base;
}
}
}
 
H

Harlan Messinger

John said:
by implementing abstract classes as nested classes

the implementation has full access (via a reference) to all the
members of the parent class

This is a variant of the alternative to multiple inheritance known as
"aggregation", and is commonly recommended even for use in C++ to avoid
the pitfalls of MI.

Your variation, by using nested classes, goes beyond inheritance insofar
as it gives the "inheriting" class even to private members of the
"parents". Ordinarily, non-nested derived classes can access protected
members of their parents but can't access private members.
 
J

John Rivers

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
 
P

Peter Duniho

John said:
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

Probably what you are looking for is something more like this:

interface IAProxy
{
void MethodFromA();
}

public class A
{
private B _b = new B();

private class B : IAProxy
{
IAProxy.MethodFromA(A a)
{
a.MethodFromA();
}
}

public IAProxy AProxy { get { return _b; } }

private MethodFromA()
{
}
}

All that said, the benefit of the above pattern is dubious IMHO. It
doesn't really have anything to do with multiple inheritance, for one.
For another, it begs the question of why, if you want to be able to call
the method "MethodFromA()", that method isn't just a public method in A.

If you could explain in a more precise, more real-world way what it is
you're trying to accomplish, perhaps some more specific advice can be given.

Pete
 
H

Harlan Messinger

John said:
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/...ess-to-nested-class-member-to-enclosing-class

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.
 
P

Peter Duniho

Harlan said:
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/...ess-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();
}
}
}
 
J

John Rivers

shame there isn't somekind of access modifier for this:

class A {
B b = new B();
public class B {
parent B() {
}
}
}

where "parent" means access limited to parent class

those other approaches are quite a mouthful

I like the public interface to a private class idea
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top