Generics; OO

M

MRe

Hi,

I hope it's OK to post OO questions here[?] I am using C# of
course..

I'm wonder if there's a clean way to do this: I have a library with
a public abstract class, 'PublicClass', that has an internal generic
type, 'T'. 'T' is of no interest to anyone calling on 'PublicClass',
only to inheriting classes. There's also several internal classes,
'InternalClassN', that inherits from 'PublicClass'. What I need is a
way for 'InternalClassN' to tell 'PublicClass' what 'T' is, without
there being a need for the calling code (using 'PublicClass') to know.
Note. 'InternalClassN' is constructed by a factory. E.g., what I'd
like to do in a magical world is (complete example at end of post)..

internal class InternalClassN : PublicClass<SomeTypeN> { .. } //
Library (specify 'T')

PublicClass pc = PublicClassFactory.Construct(..); // Calling code
(doesn't specify 'T')

...is there anything I can do to get this effect?

I know I could just move 'T' into each of 'InternalClassN', but it
seems kind of messy (especially in the more complex code in which I am
actually doing this).

Thank you for any help,
Kind regards,
Eliott

~~~ Complete example ~~~

using System;
namespace HiddenGenerics
{ class Program
{ static void Main(string[] args)
{ PublicClass pc;
pc = PublicClassFactory
.Construct("test");
}
}
public class PublicClassFactory
{ public static
PublicClass Construct
( string Name
){ switch(Name)
{ case "1": return new InternalClass1();
case "2": return new InternalClass2();
}
return null;
}
}
public abstract class PublicClass<T>
{ private T _Value;
}
public abstract class SomeType { }
internal class InternalClass1
: PublicClass<SomeType1> { }
internal class InternalClass2
: PublicClass<SomeType2> { }
internal class SomeType1 : SomeType { }
internal class SomeType2 : SomeType { }
}
 
G

Gregory A. Beamer

Hi,

I hope it's OK to post OO questions here[?] I am using C# of
course..

I'm wonder if there's a clean way to do this: I have a library with
a public abstract class, 'PublicClass', that has an internal generic
type, 'T'. 'T' is of no interest to anyone calling on 'PublicClass',
only to inheriting classes. There's also several internal classes,
'InternalClassN', that inherits from 'PublicClass'. What I need is a
way for 'InternalClassN' to tell 'PublicClass' what 'T' is, without
there being a need for the calling code (using 'PublicClass') to know.
Note. 'InternalClassN' is constructed by a factory. E.g., what I'd
like to do in a magical world is (complete example at end of post)..

Generics are constructs that allow you to defer typing to compile time,
not runtime. So you cannot magically have them defer to runtime, as you
desire. With Reflection, you can do some magic, but think it through
before you invest in this direction.

I think one issue is you are mixing up the problem domain (the actual
business problem being solved by your code construct) with your proposed
solution. And you are now stuck in solving the proposed solution as if
it were the actual problem that needs to be solved.

Either that, or this is a purely academic exercise in which you are
trying to solve a problem you have not solved before. If so, playing the
exercise through may be worth it.

Peace and Grace,


--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

Twitter: @gbworld
Blog: http://gregorybeamer.spaces.live.com

*******************************************
| Think outside the box! |
*******************************************
 
P

Peter Duniho

Hi,

I hope it's OK to post OO questions here[?] I am using C# of
course..

I'm wonder if there's a clean way to do this: I have a library with
a public abstract class, 'PublicClass', that has an internal generic
type, 'T'. 'T' is of no interest to anyone calling on 'PublicClass',
only to inheriting classes. There's also several internal classes,
'InternalClassN', that inherits from 'PublicClass'. What I need is a
way for 'InternalClassN' to tell 'PublicClass' what 'T' is, without
there being a need for the calling code (using 'PublicClass') to know.
[...]

I won't reiterate Gregory's comments, though I agree with them and think
you should consider them seriously.

In addition to what he said, I think one way to look at the issue is to
consider that you are conflating the public aspect with the implementation
aspect. As I understand your question, the issue is this:

-- You have a public, abstract class, which clients create instances
of using a factory. To the client code, internal type specificity is
irrelevant.

-- You have a public, abstract class, which provides some default
implementation for internal classes that actually provide the rest of the
implementation for the public, abstract class the client see. To the
internal classes, the internal type specificity is important.

-- You have internal classes inheriting your public, abstract class by
specifying the type parameter, causing the base generic class to behave in
type-specific ways important to the internal class.

Unfortunately, your code example doesn't answer the question "why do the
internal classes care about the type parameter for the public, abstract
class". Certainly the client code doesn't care, according to your
question. And the member field in the public, abstract class is
"private", which means that the internal classes inheriting that class
never see the field.

So, in answering the question, we are missing at least part of the
explanation as to what you're really trying to do.

That said, back to my original point. Look at the list of three things I
stated. Note that the first two are essentially independent of each
other, but you are trying to accomplish both with the same class.

It seems to me that what you really want is a NON-generic public, abstract
class, and then an internal generic, abstract class your internal classes
can inherit, and which itself inherits the non-generic public, abstract
class. Then, you can put the generic implementation detail needed by the
internal classes in a place where they can get at it, but without exposing
that implementation detail to the client code.

For example:

using System;
namespace HiddenGenerics
{ class Program
{ static void Main(string[] args)
{ PublicClass pc;
pc = PublicClassFactory
.Construct("test");
}
}
public class PublicClassFactory
{ public static
PublicClass Construct
( string Name
){ switch(Name)
{ case "1": return new InternalClass1();
case "2": return new InternalClass2();
}
return null;
}
}

public abstract class PublicClass
{
}

public abstract class InternalBaseClass<T> : PublicClass
{ private T _Value;
}

public abstract class SomeType { }

internal class InternalClass1
: InternalBaseClass<SomeType1> { }

internal class InternalClass2
: InternalBaseClass<SomeType2> { }

internal class SomeType1 : SomeType { }
internal class SomeType2 : SomeType { }
}

Even with that modification, there are some aspects of your example that
seem awkward. Maybe they are necessary and you just haven't provided
enough detail to explain why. But do consider Gregory's other comments
with respect to the overall design. It may well be that there's some more
elegant way to go about the whole thing.

Pete
 
M

MRe

  I'm wonder if there's a clean way to do this: I have a library with
a public abstract class, 'PublicClass', that has an internal generic
type, 'T'. 'T' is of no interest to anyone calling on 'PublicClass',
only to inheriting classes. There's also several internal classes,
'InternalClassN', that inherits from 'PublicClass'. What I need is a
way for 'InternalClassN' to tell 'PublicClass' what 'T' is, without
there being a need for the calling code (using 'PublicClass') to know.  
[...]
Eliott
~~~
[...]
I think one issue is you are mixing up the problem domain (the actual
business problem being solved by your code construct) with your proposed
solution. And you are now stuck in solving the proposed solution as if
it were the actual problem that needs to be solved.
[...]
Gregory A. Beamer ~~~
[...]
It seems to me that what you really want is a NON-generic public, abstract  
class, and then an internal generic, abstract class your internal classes 
can inherit, and which itself inherits the non-generic public, abstract  
class.  Then, you can put the generic implementation detail needed by the  
internal classes in a place where they can get at it, but without exposing  
that implementation detail to the client code.
[...]
Even with that modification, there are some aspects of your example that  
seem awkward.  Maybe they are necessary and you just haven't provided  
enough detail to explain why.  But do consider Gregory's other comments 
with respect to the overall design.  It may well be that there's some more  
elegant way to go about the whole thing.

Pete

Thank you Gregory and Pete for your answers.

I felt there was something awkward about my design too, but Pete,
your solution seems to fit nicely. Thank you.

When writing the post, I was aiming for concise - I guess I
overshot. Yes, there is a chunk missing on why I had the private
generic type. Below is a bit more detail on what I am trying to do,
but I believe I'm going to go with Pete's answer.

Thank you again Gregory and Pete,
Kind regards,
Eliott

~~~

So, the details are: I have several disk files of different formats,
but the same content (or different syntax, same semantics). The
library I'm writing is basically a wrapper that exposes the content of
these files though a common interface. To read each of these files
there are several parsers. The 'PublicClass' (above) is my base parser
class, and each 'InternalClassN are my specific file-format parsers.
One additional thing is that the parsers don't parse the file in one
go, they do it on-the-fly. To handle this, each parser has associated
with it a cache that holds the state of the parser at various stages
of the parsing, so randomly jumping around the file can restore the
nearest state. This cache is the private 'T' value (which in my
library actually has an internal getter (I didn't include this in the
example)). The cache is generic because each parser has it's own
description of state. Anyway, I've updated my code (as per Pete's
solution) to have a CachedParser<T>:parser from which my
SpecificParser can inherit. It also makes a lot more sense than what I
had been doing as it highlights the fact that there could be parsers
that aren't cached.
 
P

Paul

You have used the wrong factory pattern that is why you code looks wrong.

Use an Abstract Factory Pattern rather than a standard factory method.

Put myself to the test, no book in front of me...... but along these
lines....Im not sure what you are trying to achieve but....


public abstract class PublicClass
{
AbstractSomeType value;
AbstractSomeOtherType otherType;

public PublicClass CreatePublicClass ( )
{
this.CreateClasses()
}

public abstract PublicClass CreateClasses();
}

public class ConcretePublicClassFactory1
{
public AbstractSomeType someType;

public PublicClass CreateClasses()
{
this.value = new ConcreteType1();
this.otherType = new ConcreteOtherType1 ()
......etc ect
}
}

public class ConcretePublicClassFactory2
{
public AbstractSomeType someType;

public PublicClass CreateClasses()
{
this.value = new ConcreteType2();
... etc etc
}
}

public abstract AbstractSomeType
{
.....................
}

public class ConcreteType1 : AbstractSomeType{ }
public class ConcreteType2 : AbstractSomeType{ }


public abstract AbstractSomeOtherType
{
.....................
}

public class ConcreteOtherType1 : AbstractSomeOtherType{ }
 

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