![]() |
|
|
|||||||
![]() |
Java - Scope - do I need two identical classes, each with different scope? |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
I am trying to understand scope and am getting a little confused. Say
I have a public class "Triangle" with private attributes and public accessors. This class has attributes of type "Point". Point is another public class in the same package as Triangle and it, too, has public accessors. I'd like to allow a program outside the package to create a Triangle, set the Point attributes, and then call a method in the Triangle class that performs some calculation and returns a Point. So far, so good. The question is, what if I want the Point that is returned to not be modifiable by this outside program. Do I have to create two Point classes? Identical except one is public (and would be used to set the Triangle attributes) and one is default package scope(and would be returned from the calculation method)? Thanks, Ann ann |
|
|
|
|
#2 |
|
Posts: n/a
|
"ann" <> wrote in message
news: oups.com... >I am trying to understand scope and am getting a little confused. Say > I have a public class "Triangle" with private attributes and public > accessors. This class has attributes of type "Point". Point is > another public class in the same package as Triangle and it, too, has > public accessors. I'd like to allow a program outside the package to > create a Triangle, set the Point attributes, and then call a method in > the Triangle class that performs some calculation and returns a Point. > So far, so good. > > The question is, what if I want the Point that is returned to not be > modifiable by this outside program. Do I have to create two Point > classes? Identical except one is public (and would be used to set the > Triangle attributes) and one is default package scope(and would be > returned from the calculation method)? I've asked a few people about their solutions to this type of problem and haven't yet gotten a design I'm happy with. What I ended up usually doing is having 3 classes. An abstract base "Point" class, a "MutablePoint" class which extends Point and a "ImmutablePoint" class which also extends Point. Code which don't care whether the Point is mutable or not should use Point. If they specifically want a mutable point, they use MutablePoint and similarly for ImmutablePoint. Sometimes it's also useful to have utility methods to create a ImmutablePoint from a MutablePoint and vice versa. I'd love to hear suggestions for better solutions though. - Oliver Oliver Wong |
|
|
|
#3 |
|
Posts: n/a
|
Oliver Wong wrote:
> "ann" <> wrote in message > news: oups.com... >> I am trying to understand scope and am getting a little confused. >> Say I have a public class "Triangle" with private attributes and >> public accessors. This class has attributes of type "Point". Point >> is another public class in the same package as Triangle and it, too, >> has public accessors. I'd like to allow a program outside the >> package to create a Triangle, set the Point attributes, and then >> call a method in the Triangle class that performs some calculation >> and returns a Point. So far, so good. >> >> The question is, what if I want the Point that is returned to not be >> modifiable by this outside program. Do I have to create two Point >> classes? Identical except one is public (and would be used to set >> the Triangle attributes) and one is default package scope(and would >> be returned from the calculation method)? > > I've asked a few people about their solutions to this type of > problem and haven't yet gotten a design I'm happy with. What I ended > up usually doing is having 3 classes. An abstract base "Point" class, > a "MutablePoint" class which extends Point and a "ImmutablePoint" > class which also extends Point. > > Code which don't care whether the Point is mutable or not should > use Point. If they specifically want a mutable point, they use > MutablePoint and similarly for ImmutablePoint. > > Sometimes it's also useful to have utility methods to create a > ImmutablePoint from a MutablePoint and vice versa. > > I'd love to hear suggestions for better solutions though. Not necessarily better but your design can be implemented with two classes (base class immutable, derived class mutable). I guess I'd prefer that solution because I don't see the need for the third class. Then there are of course other solutions, for example, you can have a flag for modifiable state (like Ruby's #freeze and #frozen?) that prevent calling setters. Kind regards robert Robert Klemme |
|
|
|
#4 |
|
Posts: n/a
|
> > I'd love to hear suggestions for better solutions though.
> > Not necessarily better but your design can be implemented with two classes > (base class immutable, derived class mutable). I know this rule gets broken oh so often in OO land, but it violates the fundamental principle that subclasses should embody everything that the superclass is PLUS some extra features/facets/behaviours/attributes. If the base class represents something immutable, then all its subclasses should likewise be. Can you imagine what havoc would be created if Sun suddenly removed the final keyword from String, thus making it subclassable? Anyone subclassing String to produce mutable Strings would not get very far. jan V |
|
|
|
#5 |
|
Posts: n/a
|
"jan V" <> wrote in message news:rlhVe.192195$... >> > I'd love to hear suggestions for better solutions though. >> >> Not necessarily better but your design can be implemented with two >> classes >> (base class immutable, derived class mutable). > > I know this rule gets broken oh so often in OO land, but it violates the > fundamental principle that subclasses should embody everything that the > superclass is PLUS some extra features/facets/behaviours/attributes. > > If the base class represents something immutable, then all its subclasses > should likewise be. Can you imagine what havoc would be created if Sun > suddenly removed the final keyword from String, thus making it > subclassable? > Anyone subclassing String to produce mutable Strings would not get very > far. Yeah, this is the reason for 3 classes. An ImmutableFoo doesn't have an IS A relationship with a MutableFoo in either direction. (i.e. it's not the case that ImmutableFoo IS A MutableFoo, nor a MutableFoo IS A ImmutableFoo). The only thing they have in common is that they are both Foos. - Oliver Oliver Wong |
|
|
|
#6 |
|
Posts: n/a
|
jan V wrote:
>>> I'd love to hear suggestions for better solutions though. >> >> Not necessarily better but your design can be implemented with two >> classes (base class immutable, derived class mutable). > > I know this rule gets broken oh so often in OO land, but it violates > the fundamental principle that subclasses should embody everything > that the superclass is PLUS some extra > features/facets/behaviours/attributes. > > If the base class represents something immutable, then all its > subclasses should likewise be. Well, it depends. If you say that the base class represents something with public read methods and protected write methods then sub classes that have public write methods embody everything of the base class plus an extra feature. I have seen more fundamental violations of OO principles that I personally worry more about than this case. > Can you imagine what havoc would be > created if Sun suddenly removed the final keyword from String, thus > making it subclassable? Anyone subclassing String to produce mutable > Strings would not get very far. Yes, but if Sun would change this (which won't happen for quite a few reasons) then they'd likely provide means to modify the internal buffers - if they wanted String to be mutable. But this is a different story: later modification of a base class. That's something completely different from the current issue. Kind regards robert Robert Klemme |
|
|
|
#7 |
|
Posts: n/a
|
Thanks Oliver and Robert for your suggestions. I think I will try the
3 method route. Sincerely, Ann ann |
|
|
|
#8 |
|
Posts: n/a
|
ann wrote: > I am trying to understand scope and am getting a little confused. Say > I have a public class "Triangle" with private attributes and public > accessors. This class has attributes of type "Point". Point is > another public class in the same package as Triangle and it, too, has > public accessors. I'd like to allow a program outside the package to > create a Triangle, set the Point attributes, and then call a method in > the Triangle class that performs some calculation and returns a Point. > So far, so good. > > The question is, what if I want the Point that is returned to not be > modifiable by this outside program. Do I have to create two Point > classes? Identical except one is public (and would be used to set the > Triangle attributes) and one is default package scope(and would be > returned from the calculation method)? > > Thanks, > Ann On a related note, what if, instead of wanting to return a point, I want to return a Vector of Points. Can I prevent the outside program from adding or removing Points from the Vector? E.g. Vector v = triangle.performCalculation(); v.removeAll(); Ann ann |
|
|
|
#9 |
|
Posts: n/a
|
On 12 Sep 2005 08:23:02 -0700, "ann" <> wrote or
quoted : >The question is, what if I want the Point that is returned to not be >modifiable by this outside program. Do I have to create two Point >classes? Identical except one is public (and would be used to set the >Triangle attributes) and one is default package scope(and would be >returned from the calculation method)? One class can be a subset of the other. Unfortunately you can't put the accessors in a package version then seal them off in a derived public version. You create a pubic version without accessors and a second derived version with accessors and a private constructor. Unfortunately, the derived version must also be public. People trying to thwart your safety could cast a one to the other, but at least people would not accidentally get in trouble. -- Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts. Roedy Green |
|
|
|
#10 |
|
Posts: n/a
|
> On a related note, what if, instead of wanting to return a point, I
> want to return a Vector of Points. Can I prevent the outside program > from adding or removing Points from the Vector? E.g. Vector v = > triangle.performCalculation(); v.removeAll(); With a plain Vector you can't stop the outside world from changing its content, but if you were to use List as the return type, then you could use Collections.unmodifiableList(List) to manufacture an ... unmodifiable (surprise) List with which you could stop the outside program from removing any Points. jan V |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Adding classes in the web developed using NetBean IDE | crazybird_2005 | Software | 0 | 08-03-2006 02:30 PM |