473,466 Members | 1,382 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

How to control access to inner class through outer class

Consider the following class layout

public class Order
{
public ProductOrder AddProductOrder(/* variables required to create a
product order */)
{
/* Check if the product order can be added to the order */
}

public class ProductOrder
{
// This cant be private if i want to use it from the encapsulating
class!
private ProductOrder(/**/)
{
}
}
}

The idea is to control access to the inner class, because the inner class
can not exist without the outer class, but i can't make the ctor private
because it''s not visible from the encapsulating class. If anyone can solve
the above without exposing the ctor of the inner class outside of the wrapped
class I would like to hear from you. Also, if you know some great sites or
books which discuss design patterns which are relevant to business logic,
please point me in the right direction :-)
Feb 19 '06 #1
9 1843
MariusI wrote:
Consider the following class layout

public class Order
{
public ProductOrder AddProductOrder(/* variables required to
create a product order */)
{
/* Check if the product order can be added to the order */
}

public class ProductOrder
{
// This cant be private if i want to use it from the
encapsulating class!
private ProductOrder(/**/)
{
}
}
}

The idea is to control access to the inner class, because the inner
class can not exist without the outer class, but i can't make the
ctor private because it''s not visible from the encapsulating class.
If anyone can solve the above without exposing the ctor of the inner
class outside of the wrapped class I would like to hear from you.
Also, if you know some great sites or books which discuss design
patterns which are relevant to business logic, please point me in the
right direction :-)


Don't use inner classes if you're exposing the type to the outside of
the containing class. So you're exposing ProductOrder to the outside of
Order, which thus means the code outside Order knows what a
ProductOrder is, so the location of ProductOrder doesn't matter so
place it outside Order.

As ProductOrder has to rely on an Order, you can construct the
Productorder's constructor in such a way that it accepts an Order
object (and not null) and only in the constructor, not via a set
property. This way you can't create a ProductOrder without an instance
of its Order.

Though what's the relation between order and productorder? it SOUNDS
like a subtype...

FB

--
------------------------------------------------------------------------
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Feb 20 '06 #2
An order can contain one or more productOrders. A productOrder specifies a
product and how many entities you want to place an order on. There are design
patterns which expose inner classes to outside code, such as the
IEnumerable/IEnumerator pattern. The main reason for using a factory method
insted of a ctor in the ProductOrder class, is that the business rules which
controls creation of producOrders are highly dependent on the Order class. I
could of course, access the encapsulating class through the inner class, but
i wanted to apply the business logic in the class which controls it. The
outer/inner class pattern was chosen to emphasise that the innerclass is not
relevant outside of an order context and should be read-only exposed outside
of the class.

"Frans Bouma [C# MVP]" wrote:
MariusI wrote:
Consider the following class layout

public class Order
{
public ProductOrder AddProductOrder(/* variables required to
create a product order */)
{
/* Check if the product order can be added to the order */
}

public class ProductOrder
{
// This cant be private if i want to use it from the
encapsulating class!
private ProductOrder(/**/)
{
}
}
}

The idea is to control access to the inner class, because the inner
class can not exist without the outer class, but i can't make the
ctor private because it''s not visible from the encapsulating class.
If anyone can solve the above without exposing the ctor of the inner
class outside of the wrapped class I would like to hear from you.
Also, if you know some great sites or books which discuss design
patterns which are relevant to business logic, please point me in the
right direction :-)


Don't use inner classes if you're exposing the type to the outside of
the containing class. So you're exposing ProductOrder to the outside of
Order, which thus means the code outside Order knows what a
ProductOrder is, so the location of ProductOrder doesn't matter so
place it outside Order.

As ProductOrder has to rely on an Order, you can construct the
Productorder's constructor in such a way that it accepts an Order
object (and not null) and only in the constructor, not via a set
property. This way you can't create a ProductOrder without an instance
of its Order.

Though what's the relation between order and productorder? it SOUNDS
like a subtype...

FB

--
------------------------------------------------------------------------
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Feb 20 '06 #3

"MariusI" <Ma*****@discussions.microsoft.com> wrote in message
news:27**********************************@microsof t.com...
Consider the following class layout

public class Order
{
public ProductOrder AddProductOrder(/* variables required to create a
product order */)
{
/* Check if the product order can be added to the order */
}

public class ProductOrder
{
// This cant be private if i want to use it from the encapsulating
class!
private ProductOrder(/**/)
{
}
}
}

The idea is to control access to the inner class, because the inner class
can not exist without the outer class, but i can't make the ctor private
because it''s not visible from the encapsulating class. If anyone can
solve
the above without exposing the ctor of the inner class outside of the
wrapped
class I would like to hear from you. Also, if you know some great sites or
books which discuss design patterns which are relevant to business logic,
please point me in the right direction :-)


The usual way to do this is using "internal" access.

Obviously this is not totally satisfactory because it would only prevent
code from outside your assembly from creating the class but this is the
method that the framework uses and it allows you to unnest the class which
is logically wrong but makes for much less messy code.

Where are your C++ friends when you need them? :-)
Feb 20 '06 #4
The internal modifier is not satisfactory for my needs. Yes, i get to hide my
implementation between dll's, but that's not enough considering i have a
large dll with both consumer/producer classes and that means that the
consumer classes still have access.

"Nick Hounsome" wrote:

"MariusI" <Ma*****@discussions.microsoft.com> wrote in message
news:27**********************************@microsof t.com...
Consider the following class layout

public class Order
{
public ProductOrder AddProductOrder(/* variables required to create a
product order */)
{
/* Check if the product order can be added to the order */
}

public class ProductOrder
{
// This cant be private if i want to use it from the encapsulating
class!
private ProductOrder(/**/)
{
}
}
}

The idea is to control access to the inner class, because the inner class
can not exist without the outer class, but i can't make the ctor private
because it''s not visible from the encapsulating class. If anyone can
solve
the above without exposing the ctor of the inner class outside of the
wrapped
class I would like to hear from you. Also, if you know some great sites or
books which discuss design patterns which are relevant to business logic,
please point me in the right direction :-)


The usual way to do this is using "internal" access.

Obviously this is not totally satisfactory because it would only prevent
code from outside your assembly from creating the class but this is the
method that the framework uses and it allows you to unnest the class which
is logically wrong but makes for much less messy code.

Where are your C++ friends when you need them? :-)

Feb 20 '06 #5
MariusI wrote:
An order can contain one or more productOrders. A productOrder
specifies a product and how many entities you want to place an order
on. There are design patterns which expose inner classes to outside
code, such as the IEnumerable/IEnumerator pattern. The main reason
for using a factory method insted of a ctor in the ProductOrder
class, is that the business rules which controls creation of
producOrders are highly dependent on the Order class. I could of
course, access the encapsulating class through the inner class, but i
wanted to apply the business logic in the class which controls it.
The outer/inner class pattern was chosen to emphasise that the
innerclass is not relevant outside of an order context and should be
read-only exposed outside of the class.
All nice and dandy, but if you have an INNER class ProductOrder,
inside Order, it's normally not meant to be used as: (core outside
Order)
ProductOrder p = myOrder.AddProductOrder(...);

Because that suggests that the type ProductOrder is known outside the
scope of Order. If that's the case, place ProductOrder as type outside
Order.

Your suggestion that it's a design pattern isn't applicable for this
situation, because you then should use an interface which is known
outside the scope of Order, which is implemented by ProductOrder:
IFoo p = myOrder.AddProductOrder(...);

p has type IFoo (just for illustrational purposes, I cooked up this
name, but you get the idea) but is actually a ProductOrder object, but
you don't know that, nor should you care as you're working outside the
scope of Order and thus also in territory where 'ProductOrder' as a
type shouldn't be known.

If you then define ProductOrder private, you can't create an instance
of ProductOrder outside Order, however you can use it outside
ProductOrder, as you refer to it through the interface.

FB


"Frans Bouma [C# MVP]" wrote:
MariusI wrote:
Consider the following class layout

public class Order
{
public ProductOrder AddProductOrder(/* variables required to
create a product order */)
{
/* Check if the product order can be added to the order */
}

public class ProductOrder
{
// This cant be private if i want to use it from the
encapsulating class!
private ProductOrder(/**/)
{
}
}
}

The idea is to control access to the inner class, because the
inner class can not exist without the outer class, but i can't
make the ctor private because it''s not visible from the
encapsulating class. If anyone can solve the above without
exposing the ctor of the inner class outside of the wrapped class
I would like to hear from you. Also, if you know some great
sites or books which discuss design patterns which are relevant
to business logic, please point me in the right direction :-)


Don't use inner classes if you're exposing the type to the outside
of the containing class. So you're exposing ProductOrder to the
outside of Order, which thus means the code outside Order knows
what a ProductOrder is, so the location of ProductOrder doesn't
matter so place it outside Order.

As ProductOrder has to rely on an Order, you can construct the
Productorder's constructor in such a way that it accepts an Order
object (and not null) and only in the constructor, not via a set
property. This way you can't create a ProductOrder without an
instance of its Order.

Though what's the relation between order and productorder? it
SOUNDS like a subtype...

--
------------------------------------------------------------------------
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Feb 21 '06 #6
Typed DataSets provide the exact same behaviour as the one i'm implementing.
Typed DataTables are implemented as inner classes of the typed dataset and
they can only be accessed through factory methods in the outer class (typed
dataset).

"Frans Bouma [C# MVP]" wrote:
MariusI wrote:
An order can contain one or more productOrders. A productOrder
specifies a product and how many entities you want to place an order
on. There are design patterns which expose inner classes to outside
code, such as the IEnumerable/IEnumerator pattern. The main reason
for using a factory method insted of a ctor in the ProductOrder
class, is that the business rules which controls creation of
producOrders are highly dependent on the Order class. I could of
course, access the encapsulating class through the inner class, but i
wanted to apply the business logic in the class which controls it.
The outer/inner class pattern was chosen to emphasise that the
innerclass is not relevant outside of an order context and should be
read-only exposed outside of the class.


All nice and dandy, but if you have an INNER class ProductOrder,
inside Order, it's normally not meant to be used as: (core outside
Order)
ProductOrder p = myOrder.AddProductOrder(...);

Because that suggests that the type ProductOrder is known outside the
scope of Order. If that's the case, place ProductOrder as type outside
Order.

Your suggestion that it's a design pattern isn't applicable for this
situation, because you then should use an interface which is known
outside the scope of Order, which is implemented by ProductOrder:
IFoo p = myOrder.AddProductOrder(...);

p has type IFoo (just for illustrational purposes, I cooked up this
name, but you get the idea) but is actually a ProductOrder object, but
you don't know that, nor should you care as you're working outside the
scope of Order and thus also in territory where 'ProductOrder' as a
type shouldn't be known.

If you then define ProductOrder private, you can't create an instance
of ProductOrder outside Order, however you can use it outside
ProductOrder, as you refer to it through the interface.

FB


"Frans Bouma [C# MVP]" wrote:
MariusI wrote:

> Consider the following class layout
>
> public class Order
> {
> public ProductOrder AddProductOrder(/* variables required to
> create a product order */)
> {
> /* Check if the product order can be added to the order */
> }
>
> public class ProductOrder
> {
> // This cant be private if i want to use it from the
> encapsulating class!
> private ProductOrder(/**/)
> {
> }
> }
> }
>
> The idea is to control access to the inner class, because the
> inner class can not exist without the outer class, but i can't
> make the ctor private because it''s not visible from the
> encapsulating class. If anyone can solve the above without
> exposing the ctor of the inner class outside of the wrapped class
> I would like to hear from you. Also, if you know some great
> sites or books which discuss design patterns which are relevant
> to business logic, please point me in the right direction :-)

Don't use inner classes if you're exposing the type to the outside
of the containing class. So you're exposing ProductOrder to the
outside of Order, which thus means the code outside Order knows
what a ProductOrder is, so the location of ProductOrder doesn't
matter so place it outside Order.

As ProductOrder has to rely on an Order, you can construct the
Productorder's constructor in such a way that it accepts an Order
object (and not null) and only in the constructor, not via a set
property. This way you can't create a ProductOrder without an
instance of its Order.

Though what's the relation between order and productorder? it
SOUNDS like a subtype...

--
------------------------------------------------------------------------
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Feb 23 '06 #7
Mariusl,

I see where you're coming from. But I see Frans' point too. Let me
tell you what the Framework Design Guidelines book from the Microsoft
Development Series has to say about this.

"Avoid publicly exposed nested types. The only exception to this is if
variables of the nested type need to be declared only in rare scenarios
such as subclassing or other advanced customization scenarios."

Personally, I don't think your case fits the exception because callers
of your code would frequently declare the ProductOrder type so that
they have a place to land the reference returned by AddProductOrder.

Here's an example that I think does fit the exception.

public class Order
{
private ProductOrderCollection productOrders = new
ProductOrderCollection();

public ProductOrderCollection ProductOrders
{
get { return productOrders; }
}

public ProductOrderCollection : CollectionBase
{
internal ProductOrderCollection()
{
}

public void Add(ProductOrder productOrder)
{
}
}
}

public class ProductOrder
{
}

In this example ProductOrderCollection is public (though not publicly
creatable), but it would rarely be declared by calling code. There is
absolutely nothing new you can do with a local reference to
ProductOrderCollection that you can't do by simply accessing it through
the Order class. Therefore, there is little benefit in callers
declaring their own reference.

Brian
MariusI wrote:
Typed DataSets provide the exact same behaviour as the one i'm implementing.
Typed DataTables are implemented as inner classes of the typed dataset and
they can only be accessed through factory methods in the outer class (typed
dataset).

"Frans Bouma [C# MVP]" wrote:
MariusI wrote:
An order can contain one or more productOrders. A productOrder
specifies a product and how many entities you want to place an order
on. There are design patterns which expose inner classes to outside
code, such as the IEnumerable/IEnumerator pattern. The main reason
for using a factory method insted of a ctor in the ProductOrder
class, is that the business rules which controls creation of
producOrders are highly dependent on the Order class. I could of
course, access the encapsulating class through the inner class, but i
wanted to apply the business logic in the class which controls it.
The outer/inner class pattern was chosen to emphasise that the
innerclass is not relevant outside of an order context and should be
read-only exposed outside of the class.


All nice and dandy, but if you have an INNER class ProductOrder,
inside Order, it's normally not meant to be used as: (core outside
Order)
ProductOrder p = myOrder.AddProductOrder(...);

Because that suggests that the type ProductOrder is known outside the
scope of Order. If that's the case, place ProductOrder as type outside
Order.

Your suggestion that it's a design pattern isn't applicable for this
situation, because you then should use an interface which is known
outside the scope of Order, which is implemented by ProductOrder:
IFoo p = myOrder.AddProductOrder(...);

p has type IFoo (just for illustrational purposes, I cooked up this
name, but you get the idea) but is actually a ProductOrder object, but
you don't know that, nor should you care as you're working outside the
scope of Order and thus also in territory where 'ProductOrder' as a
type shouldn't be known.

If you then define ProductOrder private, you can't create an instance
of ProductOrder outside Order, however you can use it outside
ProductOrder, as you refer to it through the interface.

FB


Feb 23 '06 #8
Based on the guidelines i can see where you're critisism comes from. Thanks
for the Framework design guidelines tip. I'll dive into it right away,
looking for ways to standarize my code :-)

"Brian Gideon" wrote:
Mariusl,

I see where you're coming from. But I see Frans' point too. Let me
tell you what the Framework Design Guidelines book from the Microsoft
Development Series has to say about this.

"Avoid publicly exposed nested types. The only exception to this is if
variables of the nested type need to be declared only in rare scenarios
such as subclassing or other advanced customization scenarios."

Personally, I don't think your case fits the exception because callers
of your code would frequently declare the ProductOrder type so that
they have a place to land the reference returned by AddProductOrder.

Here's an example that I think does fit the exception.

public class Order
{
private ProductOrderCollection productOrders = new
ProductOrderCollection();

public ProductOrderCollection ProductOrders
{
get { return productOrders; }
}

public ProductOrderCollection : CollectionBase
{
internal ProductOrderCollection()
{
}

public void Add(ProductOrder productOrder)
{
}
}
}

public class ProductOrder
{
}

In this example ProductOrderCollection is public (though not publicly
creatable), but it would rarely be declared by calling code. There is
absolutely nothing new you can do with a local reference to
ProductOrderCollection that you can't do by simply accessing it through
the Order class. Therefore, there is little benefit in callers
declaring their own reference.

Brian
MariusI wrote:
Typed DataSets provide the exact same behaviour as the one i'm implementing.
Typed DataTables are implemented as inner classes of the typed dataset and
they can only be accessed through factory methods in the outer class (typed
dataset).

"Frans Bouma [C# MVP]" wrote:
MariusI wrote:

> An order can contain one or more productOrders. A productOrder
> specifies a product and how many entities you want to place an order
> on. There are design patterns which expose inner classes to outside
> code, such as the IEnumerable/IEnumerator pattern. The main reason
> for using a factory method insted of a ctor in the ProductOrder
> class, is that the business rules which controls creation of
> producOrders are highly dependent on the Order class. I could of
> course, access the encapsulating class through the inner class, but i
> wanted to apply the business logic in the class which controls it.
> The outer/inner class pattern was chosen to emphasise that the
> innerclass is not relevant outside of an order context and should be
> read-only exposed outside of the class.

All nice and dandy, but if you have an INNER class ProductOrder,
inside Order, it's normally not meant to be used as: (core outside
Order)
ProductOrder p = myOrder.AddProductOrder(...);

Because that suggests that the type ProductOrder is known outside the
scope of Order. If that's the case, place ProductOrder as type outside
Order.

Your suggestion that it's a design pattern isn't applicable for this
situation, because you then should use an interface which is known
outside the scope of Order, which is implemented by ProductOrder:
IFoo p = myOrder.AddProductOrder(...);

p has type IFoo (just for illustrational purposes, I cooked up this
name, but you get the idea) but is actually a ProductOrder object, but
you don't know that, nor should you care as you're working outside the
scope of Order and thus also in territory where 'ProductOrder' as a
type shouldn't be known.

If you then define ProductOrder private, you can't create an instance
of ProductOrder outside Order, however you can use it outside
ProductOrder, as you refer to it through the interface.

FB


Feb 28 '06 #9
Mariusl,

Well, obviously Microsoft hasn't adhered to their own standards. You
mentioned that strongly typed datasets have public nested types. I
frequently declare references of those types so I don't think they fit
the exception either and yet Microsoft still choose to do it that way.

Brian

MariusI wrote:
Based on the guidelines i can see where you're critisism comes from. Thanks
for the Framework design guidelines tip. I'll dive into it right away,
looking for ways to standarize my code :-)

"Brian Gideon" wrote:
Mariusl,

I see where you're coming from. But I see Frans' point too. Let me
tell you what the Framework Design Guidelines book from the Microsoft
Development Series has to say about this.

"Avoid publicly exposed nested types. The only exception to this is if
variables of the nested type need to be declared only in rare scenarios
such as subclassing or other advanced customization scenarios."

Personally, I don't think your case fits the exception because callers
of your code would frequently declare the ProductOrder type so that
they have a place to land the reference returned by AddProductOrder.

Here's an example that I think does fit the exception.

public class Order
{
private ProductOrderCollection productOrders = new
ProductOrderCollection();

public ProductOrderCollection ProductOrders
{
get { return productOrders; }
}

public ProductOrderCollection : CollectionBase
{
internal ProductOrderCollection()
{
}

public void Add(ProductOrder productOrder)
{
}
}
}

public class ProductOrder
{
}

In this example ProductOrderCollection is public (though not publicly
creatable), but it would rarely be declared by calling code. There is
absolutely nothing new you can do with a local reference to
ProductOrderCollection that you can't do by simply accessing it through
the Order class. Therefore, there is little benefit in callers
declaring their own reference.

Brian


Mar 2 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Hal Vaughan | last post by:
First, I am aware of both SwingUtilities.invokeLater(), and of using Thread to create a new thread.  These are part of the problem. I want to have something running in the background, while the...
9
by: John Harrison | last post by:
Both gcc 3.3.1 and VC++ 7.1 compile the following code. struct Outer { struct Inner { int f() { return c; } }; private: static const int c;
5
by: Fabio Rossi | last post by:
Hi! I'm learning C++ from the book "Thinking in C++". Now I'm reading about nested classes and access control. I have written this code #include <iostream> class Outer { private: int...
166
by: Graham | last post by:
This has to do with class variables and instances variables. Given the following: <code> class _class: var = 0 #rest of the class
4
by: Dennis C. Drumm | last post by:
Is there a way with C# to allow one class access to a method or field of another class, without making that method or field visible to all other classes, as would be the case when making the method...
6
by: MilanB | last post by:
Hello //----------------- I have following situation: public class Class1 { public struct Struct1 { public void Function1() {
2
by: dobest03 | last post by:
Hi. Are there any way to access the integer member 'a' of outer structure from inner structure's member function func_inner()? See below the structure... Thanks. struct outer {
6
by: Wijaya Edward | last post by:
Can we make loops control in Python? What I mean is that whether we can control which loops to exit/skip at the given scope. For example in Perl we can do something like: OUT: foreach my $s1...
5
by: Martijn Mulder | last post by:
A construction like this: class Outer { class Inner:Outer { } } compiles without problem but does it introduce infinity?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.