By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,732 Members | 831 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,732 IT Pros & Developers. It's quick & easy.

Re: Provide access to a class without access to the constructor

P: n/a
On Fri, 11 Apr 2008 01:43:52 -0700, Weeble <cl************@gmail.com>
wrote:
The difference is that A has ConsumeB, which takes an IB as a
parameter.
That's not a difference. The code example you compared to has the
implication that A will use the IB instance passed back from the GetB
method. After all, that's why the return type for GetB is IB, rather than
B.
It can't take a B as a parameter, because B is private to
A. So it only has strong guarantees about the methods that are
available, not what they do.
That's why you define the interface in a way that provides the guarantee
you need. This doesn't enforce the semantics, but it does provide
implementors with very strond indications regarding what the
implementations should do

For example:
Well, in the rather more complicated example that inspired this, B
contains a transformation matrix which, at least when constructed by
A, is known to be a rotation. It's quite awkward (though certainly
possible) to verify if a given matrix is a pure rotation, but it's
quite easy to compose one out of other known rotations.
In that case, you need to write an interface that represents itself only
in terms of rotation. It can return a matrix (cloned, so that you don't
allow external mutation of internal state) as a convenience, but the API
should be strictly in terms of rotating. Even better is for the interface
to be immutable. You can only create an instance by providing a rotation,
or by combining existing instances. The interface would include the
latter operation, and of course the implementor provides the former.

You could either make the assumption that the implementor has followed the
semantics of the interface or, if you really think it's that important,
it's not hard to inspect a transformation matrix and determine whether it
only rotates. This is more flexible than insisting on your own
implementation, if doing that bothers you.

Personally, I think it's fine to make an assumption about whether the
interface is implemented with the intended semantics. For one, you never
know: perhaps some day someone will find a need to provide an
implementation that does something other than just rotate. For another,
if it's true that your own code will really break unless that condition is
met, then that should be readily apparent as soon as someone tries to use
an incorrect implementation. To some extent, I find it reasonable to rely
on testing to ensure correctness. Not everything about the correctness of
the code can be represented by the API that code exposes.

That said, I have the impression that you're not all that enthusiastic
about using interfaces to address this. And that's fine.
[...]
>You can't really guarantee that. But you can, as I mentioned in my
previous reply to your message, at least check the type of the
implementing instance to make sure it's B. Presumably that's really all
you care about anyway.

I certainly *could* do, but that feels very against-the-grain. It
seems like it should be possible to solve this at compile-time. I was
inspired by recent articles by Eric Lippert, such as:
http://blogs.msdn.com/ericlippert/ar...why-can-i.aspx
as well as his previous series on immutable data types. It made me
think that I could and should be using the type system and access
controls to provide stronger guarantees about the behaviour of my
classes.
Well, as has been noted, you can. I think that using "internal" is the
best way, personally. I agree that nesting the classes can get out of
hand, and for no real good reason.

You might need to adjust your thinking, so that you're willing to treat
assemblies as legitimate compilation divisions. But it seems like they
offer the separation you're looking for here.

Pete

Jun 27 '08 #1
Share this Question
Share on Google+
1 Reply


P: n/a
On Apr 11, 6:32 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
On Fri, 11 Apr 2008 01:43:52 -0700, Weeble <clockworksa...@gmail.com>
wrote:
The difference is that A has ConsumeB, which takes an IB as a
parameter.

That's not a difference. The code example you compared to has the
implication that A will use the IB instance passed back from the GetB
method. After all, that's why the return type for GetB is IB, rather than
B.
I don't quite follow you here. GetB returns an IB, but we do know it's
really a B. GetB is a public method, and B is private, so it could not
have a return type of B. In contrast, the IB passed into ConsumeB
really could be some non-B class.

[Rotation stuff]
In that case, you need to write an interface that represents itself only
in terms of rotation. It can return a matrix (cloned, so that you don't
allow external mutation of internal state) as a convenience, but the API
should be strictly in terms of rotating. Even better is for the interface
to be immutable.
I do like immutable classes. :)

That said, I have the impression that you're not all that enthusiastic
about using interfaces to address this. And that's fine.
In the end I didn't use interfaces for this one. Rotations have a
public constructor that guarantees to make a proper rotation, and a
private constructor that is used by the methods that compose or
transpose rotations.
You might need to adjust your thinking, so that you're willing to treat
assemblies as legitimate compilation divisions. But it seems like they
offer the separation you're looking for here.
Actually, I was originally going to use assemblies for these kind of
divisions, but apparently it causes some sort of problems to have too
many assemblies, so I've been discouraged from doing this. (I can see
that it's annoying to have to add lots of references to each project,
though.) And when I have one huge assembly with lots of classes, some
of which need access to others' internal methods, it gets hard to make
it clear which classes should be using the internal methods and which
shouldn't.

Thanks for all the advice! It's been an interesting puzzle, but I
think I've finally dodged the nasty parts and found a solution that's
going to be at least moderately idiot-proof.

Weeble.
Jun 27 '08 #2

This discussion thread is closed

Replies have been disabled for this discussion.