Scope - do I need two identical classes, each with different scope?

Discussion in 'Java' started by ann, Sep 12, 2005.

  1. ann

    ann Guest

    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, Sep 12, 2005
    #1
    1. Advertising

  2. ann

    Oliver Wong Guest

    "ann" <> wrote in message
    news:...
    >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, Sep 12, 2005
    #2
    1. Advertising

  3. Oliver Wong wrote:
    > "ann" <> wrote in message
    > news:...
    >> 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, Sep 12, 2005
    #3
  4. ann

    jan V Guest

    > > 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, Sep 12, 2005
    #4
  5. ann

    Oliver Wong Guest

    "jan V" <> wrote in message
    news:rlhVe.192195$-ops.be...
    >> > 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, Sep 12, 2005
    #5
  6. 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, Sep 12, 2005
    #6
  7. ann

    ann Guest

    Thanks Oliver and Robert for your suggestions. I think I will try the
    3 method route.

    Sincerely,
    Ann
    ann, Sep 12, 2005
    #7
  8. ann

    ann Guest

    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, Sep 12, 2005
    #8
  9. ann

    Roedy Green Guest

    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, Sep 12, 2005
    #9
  10. ann

    jan V Guest

    > 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, Sep 12, 2005
    #10
  11. ann

    Roedy Green Guest

    Roedy Green, Sep 12, 2005
    #11
  12. ann

    Roedy Green Guest

    On Mon, 12 Sep 2005 15:26:44 GMT, "Oliver Wong" <>
    wrote or quoted :

    > I'd love to hear suggestions for better solutions though.


    Here is one more approach. You write a class with accessor methods
    then have it implement an interface without them, just exposing what
    you want. You return objects to your end users only by the interface
    reference. The accessors have package scope.
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Again taking new Java programming contracts.
    Roedy Green, Sep 12, 2005
    #12
  13. Re: Scope - do I need two identical classes, each with differentscope?

    [Re: class Triangle, containing mutable Points, providing immutable
    views of those Points]

    Roedy Green wrote:
    > Here is one more approach. You write a class with accessor methods
    > then have it implement an interface without them, just exposing what
    > you want. You return objects to your end users only by the interface
    > reference. The accessors have package scope.


    That is probably about what I would do, as it makes for looser coupling
    between Triangle and Point, and also decouples client applications from
    Point altogether. Giving the accessors default/package-private access
    does ensure that the client cannot cast the object to Point to get at
    the accessors, but I might not go quite that far. If I *never* want
    clients to be able to mutate Points then I might do, but on the other
    hand I might instead make the whole class package-private and use only
    the related interface in the public API. If I ever want clients to be
    able to mutate Points in some other context then the accessors need to
    be public.

    --
    John Bollinger
    John C. Bollinger, Sep 13, 2005
    #13
  14. Re: Scope - do I need two identical classes, each with differentscope?

    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
    >


    Note that in some cases there is an alternative strategy - return a
    clone of the Point, so that you don't have to care of the caller
    modifies it.

    Patricia
    Patricia Shanahan, Sep 13, 2005
    #14
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Prabh
    Replies:
    4
    Views:
    4,108
    Malcolm Dew-Jones
    Aug 11, 2004
  2. Neroku
    Replies:
    12
    Views:
    544
    Oliver Wong
    Feb 12, 2007
  3. Juha Nieminen
    Replies:
    3
    Views:
    402
    Marcus Kwok
    Apr 30, 2007
  4. Replies:
    4
    Views:
    327
    redblue
    Nov 3, 2007
  5. Igor Nn
    Replies:
    7
    Views:
    426
    Johnny Morrice
    May 28, 2011
Loading...

Share This Page