Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #38646 > unrolled thread

Overloading methods question

Started byRhino <no_offline_contact@example.com>
First post2018-10-24 17:04 -0400
Last post2018-10-25 16:07 -0400
Articles 20 on this page of 29 — 6 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Overloading methods question Rhino <no_offline_contact@example.com> - 2018-10-24 17:04 -0400
    Re: Overloading methods question Arne Vajhøj <arne@vajhoej.dk> - 2018-10-24 18:56 -0400
    Re: Overloading methods question Joerg Meier <joergmmeier@arcor.de> - 2018-10-25 10:13 +0200
      Re: Overloading methods question Rhino <no_offline_contact@example.com> - 2018-10-25 15:53 -0400
        Re: Overloading methods question Eric Douglas <e.d.programmer@gmail.com> - 2018-10-25 13:58 -0700
          Re: Overloading methods question Eric Sosman <esosman@comcast-dot-net.invalid> - 2018-10-25 17:49 -0400
            Re: Overloading methods question Martin Gregorie <martin@mydomain.invalid> - 2018-10-25 22:29 +0000
              Re: Overloading methods question Arne Vajhøj <arne@vajhoej.dk> - 2018-10-25 20:08 -0400
                Re: Overloading methods question Martin Gregorie <martin@mydomain.invalid> - 2018-10-26 00:37 +0000
                  Re: Overloading methods question Arne Vajhøj <arne@vajhoej.dk> - 2018-10-25 21:42 -0400
                  Re: Overloading methods question Joerg Meier <joergmmeier@arcor.de> - 2018-10-26 12:46 +0200
                  Re: Overloading methods question Eric Sosman <esosman@comcast-dot-net.invalid> - 2018-10-26 07:50 -0400
                    Re: Overloading methods question Martin Gregorie <martin@mydomain.invalid> - 2018-10-26 19:33 +0000
                      Re: Overloading methods question Eric Douglas <e.d.programmer@gmail.com> - 2018-10-26 13:13 -0700
                      Re: Overloading methods question Arne Vajhøj <arne@vajhoej.dk> - 2018-10-26 20:58 -0400
                        Re: Overloading methods question Martin Gregorie <martin@mydomain.invalid> - 2018-10-27 22:36 +0000
                          Re: Overloading methods question Arne Vajhøj <arne@vajhoej.dk> - 2018-10-27 19:38 -0400
                            Re: Overloading methods question Martin Gregorie <martin@mydomain.invalid> - 2018-10-28 10:39 +0000
                              Re: Overloading methods question Eric Sosman <esosman@comcast-dot-net.invalid> - 2018-10-28 07:54 -0400
            Re: Overloading methods question Eric Douglas <e.d.programmer@gmail.com> - 2018-10-26 06:26 -0700
        Re: Overloading methods question Joerg Meier <joergmmeier@arcor.de> - 2018-10-26 12:52 +0200
          Re: Overloading methods question Rhino <no_offline_contact@example.com> - 2018-10-26 22:10 -0400
            Re: Overloading methods question Eric Sosman <esosman@comcast-dot-net.invalid> - 2018-10-27 07:43 -0400
              Re: Overloading methods question Rhino <no_offline_contact@example.com> - 2018-10-29 14:40 -0400
                Re: Overloading methods question Eric Sosman <esosman@comcast-dot-net.invalid> - 2018-10-29 16:39 -0400
            Re: Overloading methods question Eric Douglas <e.d.programmer@gmail.com> - 2018-10-29 05:07 -0700
              Re: Overloading methods question Rhino <no_offline_contact@example.com> - 2018-10-29 14:41 -0400
    Re: Overloading methods question Eric Sosman <esosman@comcast-dot-net.invalid> - 2018-10-25 07:49 -0400
      Re: Overloading methods question Rhino <no_offline_contact@example.com> - 2018-10-25 16:07 -0400

Page 1 of 2  [1] 2  Next page →


#38646 — Overloading methods question

FromRhino <no_offline_contact@example.com>
Date2018-10-24 17:04 -0400
SubjectOverloading methods question
Message-ID<pqqmoq$jeo$1@dont-email.me>
Is it better to overload a single method name several times or to create 
uniquely-named methods to accomplish similar work?

I am in the midst of rewriting some old convenience methods that work 
with dates and times but use the old Calendar and java.util.Time 
classes. I know that it is far better to use the java.time.* packages now.

In the course of revising my methods to use the Java 8 classes, it has 
occurred to me that I should have several variants of some of the 
methods. For instance, one of my methods determines the name of the 
current month.

It seems reasonable to me that I might at some point need to know the 
name of the current month:
- in either short or long version - i.e. "Oct" or "October"
- in the local timezone or a different one (after all, while it may be 
late in the day on Oct 31 in my timezone, it may already be early Nov 1 
a few timezones away)

APPROACH 1:
I could have several overloaded versions of a single method. For instance:
- getCurrentMonthName(boolean fullMonthName) and assume local time zone
- getCurrentMonthName(ZoneId zoneId) and assume full month name
- getCurrentMonthName(boolean fullMonthName, ZoneId zoneId) and assume 
nothing
- getCurrentMonthName() and assume local time zone and full month name

APPROACH 2:
Or I could do this:
- getCurrentMonthNameLocal(boolean fullMonthName) and assume local time zone
- getCurrentMonthNameRemote(boolean fullMonthName, ZoneId zoneId)
  and assume nothing

APPROACH 3:
I could even do this:
- getCurrentMonthNameFullLocal() and assume local time zone
- getCurrentMonthNameShortLocal() and assume local time zone
- getCurrentMonthNameFullRemote(ZoneId zoneId) and use specified time zone
- getCurrentMonthNameShortRemote(ZoneId zoneId) and use specified time zone

APPROACH 4:
Or I could reduce the number of methods I need by having only this:
- getCurrentMonthName(boolean fullMonthName, ZoneId) which would force 
users to supply a value for the boolean and the zoneId every time even 
if they wanted the local time zone

Which is the best design and, most importantly, WHY? I expect there is a 
basic design precept somewhere that helps a developer decide which is 
the best way to go in circumstances like these. It would be helpful to 
learn (or rediscover) this principle.

Can anyone help me out?

In the absence of such a principle, it seems to me that I need to weigh 
the costs of each approach against the benefits and see which is the 
best balance. For instance, Approach 4 has the benefit of requiring me 
to code only one method to get the current month but means the method is 
more complex and probably has more conditions to test in unit test. It 
may also be more work for the person trying to use these classes as they 
have to understand the meaning of the parameters and figure out how to 
set the desired values. (I'm just learning the Java 8 time classes and 
didn't know what a zoneId was 24 hours ago, let alone how to set it and 
what values I could use. A developer using these classes might be in the 
same boat.)

-- 
Rhino

[toc] | [next] | [standalone]


#38647

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-10-24 18:56 -0400
Message-ID<pqqtbi$lr$1@gioia.aioe.org>
In reply to#38646
On 10/24/2018 5:04 PM, Rhino wrote:
> Is it better to overload a single method name several times or to create 
> uniquely-named methods to accomplish similar work?

> It seems reasonable to me that I might at some point need to know the 
> name of the current month:
> - in either short or long version - i.e. "Oct" or "October"
> - in the local timezone or a different one (after all, while it may be 
> late in the day on Oct 31 in my timezone, it may already be early Nov 1 
> a few timezones away)
> 
> APPROACH 1:
> I could have several overloaded versions of a single method. For instance:
> - getCurrentMonthName(boolean fullMonthName) and assume local time zone
> - getCurrentMonthName(ZoneId zoneId) and assume full month name
> - getCurrentMonthName(boolean fullMonthName, ZoneId zoneId) and assume 
> nothing
> - getCurrentMonthName() and assume local time zone and full month name
> 
> APPROACH 2:
> Or I could do this:
> - getCurrentMonthNameLocal(boolean fullMonthName) and assume local time 
> zone
> - getCurrentMonthNameRemote(boolean fullMonthName, ZoneId zoneId)
>   and assume nothing
> 
> APPROACH 3:
> I could even do this:
> - getCurrentMonthNameFullLocal() and assume local time zone
> - getCurrentMonthNameShortLocal() and assume local time zone
> - getCurrentMonthNameFullRemote(ZoneId zoneId) and use specified time zone
> - getCurrentMonthNameShortRemote(ZoneId zoneId) and use specified time zone
> 
> APPROACH 4:
> Or I could reduce the number of methods I need by having only this:
> - getCurrentMonthName(boolean fullMonthName, ZoneId) which would force 
> users to supply a value for the boolean and the zoneId every time even 
> if they wanted the local time zone
> 
> Which is the best design and, most importantly, WHY? I expect there is a 
> basic design precept somewhere that helps a developer decide which is 
> the best way to go in circumstances like these. It would be helpful to 
> learn (or rediscover) this principle.

I would go for approach #5:

getCurrentMonth(boolean fullMonthName)
getCurrentMonth(boolean fullMonthName, ZoneId zoneId)

My logic:
* I expect the method name in a get to explain what it is getting
   and any arguments to qualify how it should be getting it and
   that points to #2 and
* and ZoneId is sufficient rare to warrant a default value and
   since Java does not have defaults that means an overload

Arne

[toc] | [prev] | [next] | [standalone]


#38648

FromJoerg Meier <joergmmeier@arcor.de>
Date2018-10-25 10:13 +0200
Message-ID<1b2bqd7oqzez6$.sfpve8lwmic2.dlg@40tude.net>
In reply to#38646
On Wed, 24 Oct 2018 17:04:27 -0400, Rhino wrote:

> Is it better to overload a single method name several times or to create 
> uniquely-named methods to accomplish similar work?

I would argue that you should overload methods that return the same thing,
but have separate methods for returning different things. In that spirit, I
would overload the methods with an without a zone, but have separate
methods for gettting the full name, as I suspect from your posting that
those do in fact return something different.

That being said, while this was probably just an example, I should point
out that this is generally the completely wrong approach and kind of
violates sensible object oriented design: return the month instead, and let
the caller ask the month what it's called. That's what java.time.Month is
for.

Liebe Gruesse,
		Joerg

-- 
"Immer wieder erstaunlich, wie lächerlich man sich doch machen kann und
sich dabei noch toll finden." 
                        - Hartmut Kraus, 19.3.2017 in de.soc.recht.misc

Ich lese meine Emails nicht, replies to Email bleiben also leider
ungelesen.

[toc] | [prev] | [next] | [standalone]


#38650

FromRhino <no_offline_contact@example.com>
Date2018-10-25 15:53 -0400
Message-ID<pqt6v0$e65$1@dont-email.me>
In reply to#38648
On 2018-10-25 4:13 AM, Joerg Meier wrote:
> On Wed, 24 Oct 2018 17:04:27 -0400, Rhino wrote:
> 
>> Is it better to overload a single method name several times or to create
>> uniquely-named methods to accomplish similar work?
> 
> I would argue that you should overload methods that return the same thing,
> but have separate methods for returning different things. In that spirit, I
> would overload the methods with an without a zone, but have separate
> methods for gettting the full name, as I suspect from your posting that
> those do in fact return something different.
> 
> That being said, while this was probably just an example, I should point
> out that this is generally the completely wrong approach and kind of
> violates sensible object oriented design: return the month instead, and let
> the caller ask the month what it's called. That's what java.time.Month is
> for.
> 
Actually, it was a "real life example". That is one of the methods I am 
rewriting
in my class of convenience methods.

I was intrigued by your suggestion that I should just return the month 
and let the caller ask the month what it is called. I wasn't sure what 
you mean by that. but I wrote a bit of code and came up with this:

static java.time.Month getCurrentMonth() {

LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());

return zdt.getMonth();
}

Then, in the code which calls the convenience method, something like this:

String fullMonthName = 
CurrentDateTimeUtils.getCurrentMonth().getDisplayName(TextStyle.FULL, 
new Locale("de", "DE"))); //gets full month name in German e.g. Oktober
String shortMonthName =
CurrentDateTimeUtils.getCurrentMonth().getDisplayName(TextStyle.SHORT, 
new Locale("de", "DE"))); //gets short month name in German e.g. Okt.
int numericMonth = CurrentDateTimeUtils.getCurrentMonth().getValue(); 
//gets numeric value of month e.g. 10 for October

Or did you have something different in mind?

I rather like the approach you're suggesting. If I give the 
responsibility of deciding which version of the month name people want 
back to the calling program, that simplifies my convenience class so 
that I need fewer methods while leaving it entirely possible for the 
calling program to get the month information in any format it likes 
since all the possible formats can be derived from what the convenience 
method returns.

Either way, the program using my convenience method has to decide what 
it wants - and will get what it wants - so it's very reasonable to 
design the convenience class the way you suggest.


-- 
Rhino

[toc] | [prev] | [next] | [standalone]


#38652

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-10-25 13:58 -0700
Message-ID<75ad8b55-3def-4ec1-b46b-65ecd971d0fe@googlegroups.com>
In reply to#38650
On Thursday, October 25, 2018 at 3:53:15 PM UTC-4, Rhino wrote:
> static java.time.Month getCurrentMonth() {
> 
> LocalDateTime ldt = LocalDateTime.now();
> ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
> 
> return zdt.getMonth();
> }
> 
> Then, in the code which calls the convenience method, something like this:
> 
> String fullMonthName = 
> CurrentDateTimeUtils.getCurrentMonth().getDisplayName(TextStyle.FULL, 
> new Locale("de", "DE"))); //gets full month name in German e.g. Oktober
> String shortMonthName =
> CurrentDateTimeUtils.getCurrentMonth().getDisplayName(TextStyle.SHORT, 
> new Locale("de", "DE"))); //gets short month name in German e.g. Okt.
> int numericMonth = CurrentDateTimeUtils.getCurrentMonth().getValue(); 
> //gets numeric value of month e.g. 10 for October
> 
> Or did you have something different in mind?
> 
> I rather like the approach you're suggesting. If I give the 
> responsibility of deciding which version of the month name people want 
> back to the calling program, that simplifies my convenience class so 
> that I need fewer methods while leaving it entirely possible for the 
> calling program to get the month information in any format it likes 
> since all the possible formats can be derived from what the convenience 
> method returns.
> 
> Either way, the program using my convenience method has to decide what 
> it wants - and will get what it wants - so it's very reasonable to 
> design the convenience class the way you suggest.
> 
> 
> -- 
> Rhino

Yes, that looks right.  The key to overload is the return value.  Use the same exact method name and add parameters if you're returning the same value.  Use boolean where there are exactly 2 possibilities (print duplex? yes or no).  Use enums where there could be more than 2 possibilities or the parameter itself is simply not clear.  You can have the method return the month in formatted string if one of your parameters accepts an enum to tell it which format.  In this particular case returning the month object from the java time class makes sense if it already has enums to tell it how to format.

[toc] | [prev] | [next] | [standalone]


#38653

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2018-10-25 17:49 -0400
Message-ID<pqtdpa$nl4$1@dont-email.me>
In reply to#38652
On 10/25/2018 4:58 PM, Eric Douglas wrote:
> [...]
> Use boolean where there are exactly 2 possibilities (print duplex? yes or no).  [...]

     Use booleans where there exactly two possibilities *and* where
their associations with `true' and `false' are flat-out obvious.

	/** An old-fashioned binary-gendered person. */
	public class Person {
	    /** A poorly-designed constructor API. */
	    public Person(Name name, boolean gender) {
	...

     Things would be a little bit better if `gender' were renamed to
`isMale' or `isFemale', but even with the improvement it's not great:

	Person flawedSage = new Person(new Name("Kao", "Li"), false);

... is not especially transparent.

     Also, be careful to distinguish between "there are exactly two
possibilities" and "I have thought of only two possibilities."  It
is perhaps instructive that the example given would not work for the
printer that sits on my desk at this moment, which has *five* modes
for duplexing:

     One-sided

     Two-sided (automatic, flip on long axis)

     Two-sided (automatic, flip on short axis)

     Two-sided (manual, flip on long axis)

     Two-sided (manual, flip on short axis)

     (In the "automatic" modes the printer marks one side but doesn't
spit the page out, then sucks it back in and does the second side.
In the "manual" modes it prints and ejects all the back sides, then
you re-insert the stack in the paper supply and it prints the formerly-
blank fronts.  "Automatic" is more convenient, "Manual" can be faster
for long documents.)

     Duplex-or-not is, as suggested, a Yes/No question -- but if the
answer is Yes the answer is incomplete, lacking essential detail.
A good API offers (relatively) straightforward ways to supply all
the necessary information.

-- 
esosman@comcast-dot-net.invalid
Eight hundred nineteen days to go.

[toc] | [prev] | [next] | [standalone]


#38654

FromMartin Gregorie <martin@mydomain.invalid>
Date2018-10-25 22:29 +0000
Message-ID<pqtg50$ga7$1@news.albasani.net>
In reply to#38653
On Thu, 25 Oct 2018 17:49:28 -0400, Eric Sosman wrote:

> On 10/25/2018 4:58 PM, Eric Douglas wrote:
>> [...]
>> Use boolean where there are exactly 2 possibilities (print duplex? yes
>> or no).  [...]
> 
>      Use booleans where there exactly two possibilities *and* where
> their associations with `true' and `false' are flat-out obvious.
> 
> 	/** An old-fashioned binary-gendered person. */
> 	public class Person {
> 	    /** A poorly-designed constructor API. */ public Person(Name 
name,
> 	    boolean gender) {
> 	...
> 
>      Things would be a little bit better if `gender' were renamed to
> `isMale' or `isFemale', but even with the improvement it's not great:
> 
> 	Person flawedSage = new Person(new Name("Kao", "Li"), false);
> 
> ... is not especially transparent.
>
In those circumstances I tend to define constants in the consuming class. 
In the OP's case I'd probably change the boolean to an int named 
nameFormat and declare the constants:

public static final int LONG 1;
public static final int SHORT 2;

and my code in the class would also use the SHORT and LONG constants 
because: 

(a) this way I don't have to create an enum and the javadocs will
    document the values automatically 
(b) both the method call and the internal code are easy to read
(c) the constant values have no hidden uses so the actual values used
    don't matter as long as they're different
(d) if additional values are needed in future they're easy to add

I realise that this approach probably betrays my C background, but is  
anything else about it wrong enough that it should cause me to use enums 
instead? 


-- 
Martin    | martin at
Gregorie  | gregorie dot org

[toc] | [prev] | [next] | [standalone]


#38655

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-10-25 20:08 -0400
Message-ID<pqtluk$gg9$1@gioia.aioe.org>
In reply to#38654
On 10/25/2018 6:29 PM, Martin Gregorie wrote:
> In those circumstances I tend to define constants in the consuming class.
> In the OP's case I'd probably change the boolean to an int named
> nameFormat and declare the constants:
> 
> public static final int LONG 1;
> public static final int SHORT 2;
> 
> and my code in the class would also use the SHORT and LONG constants
> because:
> 
> (a) this way I don't have to create an enum and the javadocs will
>      document the values automatically
> (b) both the method call and the internal code are easy to read
> (c) the constant values have no hidden uses so the actual values used
>      don't matter as long as they're different
> (d) if additional values are needed in future they're easy to add
> 
> I realise that this approach probably betrays my C background, but is
> anything else about it wrong enough that it should cause me to use enums
> instead?

Enum achives the same 4 goals (except obviously the first half
of #a - not having to define an enum).

And enum will be better/easier documented for method arguments.

And enum is type safe while int constants are not.

foobar(7 * LONG + SHORT);

will be accepted by the compiler but have undefined semantics.

Arne

[toc] | [prev] | [next] | [standalone]


#38656

FromMartin Gregorie <martin@mydomain.invalid>
Date2018-10-26 00:37 +0000
Message-ID<pqtnjm$abo$1@news.albasani.net>
In reply to#38655
On Thu, 25 Oct 2018 20:08:54 -0400, Arne Vajhøj wrote:

> Enum achives the same 4 goals (except obviously the first half of #a -
> not having to define an enum).
>
Sure, though being defined outside a class that is the only place its 
used (apart from when its supplied as a method argument) as we've been 
discussing does separate each constant definition and its documentation 
from the class definition and documentation
 
> And enum will be better/easier documented for method arguments.
> 
Apart from the separation mentioned above. I see this as a disadvantage 
though you may not.

> And enum is type safe while int constants are not.
>
AFAIK that is not relevant if the constant is defined as static final.
 
> will be accepted by the compiler but have undefined semantics. 
>
Agreed, but being basically a mildly paranoid C programmer I tend to 
validate all arguments, including those created with a #define (C) or as 
static final int (Java) and you really shouldn't be defining a constant 
unless its one of the above or part of an enum.

So far, it all looks a bit like swings and roundabouts to me except, of 
course, if your enum contains logic rather than being simply a list of 
constants.
 

-- 
Martin    | martin at
Gregorie  | gregorie dot org

[toc] | [prev] | [next] | [standalone]


#38657

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-10-25 21:42 -0400
Message-ID<pqtrdv$mu8$1@gioia.aioe.org>
In reply to#38656
On 10/25/2018 8:37 PM, Martin Gregorie wrote:
> On Thu, 25 Oct 2018 20:08:54 -0400, Arne Vajhøj wrote:
>> Enum achives the same 4 goals (except obviously the first half of #a -
>> not having to define an enum).
>>
> Sure, though being defined outside a class that is the only place its
> used (apart from when its supplied as a method argument) as we've been
> discussing does separate each constant definition and its documentation
> from the class definition and documentation

I am not sure that I can follow that argument.

If you make the enum nested instead of top level then it will be in the
same source file at the same place as the int constants would have been.

And in the java docs you just click on the type to get to the java docs
instead of scrolling around searching for info you need.

>> And enum will be better/easier documented for method arguments.
>>
> Apart from the separation mentioned above. I see this as a disadvantage
> though you may not.

public void foobar(MyEnum val)

is simpler than:

/**
  * ...
  * Note: val takes the values SomeClass.Const1, ..., SomeClass.Constn
  */
public void foobar(int val)

>> And enum is type safe while int constants are not.
>>
> AFAIK that is not relevant if the constant is defined as static final.

It is as the example shown.

>> will be accepted by the compiler but have undefined semantics.
>>
> Agreed, but being basically a mildly paranoid C programmer I tend to
> validate all arguments, including those created with a #define (C) or as
> static final int (Java) and you really shouldn't be defining a constant
> unless its one of the above or part of an enum.

Yes. But that is a runtime error instead of a compile time error.

Moving errors from runtime to compile time is what type safety
is all about.

And many people (but not all) consider doing that a good thing.

Arne

[toc] | [prev] | [next] | [standalone]


#38658

FromJoerg Meier <joergmmeier@arcor.de>
Date2018-10-26 12:46 +0200
Message-ID<16nzai1tzrp1d.4yh8ynprin5c$.dlg@40tude.net>
In reply to#38656
On Fri, 26 Oct 2018 00:37:10 +0000 (UTC), Martin Gregorie wrote:

>> And enum is type safe while int constants are not.
> AFAIK that is not relevant if the constant is defined as static final.

martinsMethod(BoxLayout.X_AXIS); // what now ?

The above may work, or not work, or change what it does between Java
versions, and will not be detected during compile time. I know it looks too
obvious to get wrong, and in this example it is, but once you start having
people copy and paste code around and extract parameters to variables and
fields, it becomes less obvious that there is a problem here.

If you feel the above example is too contrived:

foo(boolean bigDesign) {
	int designSetting1;
	int designSetting2;
	if (bigDesign) {
		designSetting1 = BoxLayout.X_AXIS;
		designSetting2 = MartinsClass.LONG;
	} else {
		designSetting1 = BoxLayout.Y_AXIS;
		designSetting2 = MartinsClass.SHORT;
	}
	
	// ...
	// ...
	// ...
	// ...
	// ...
	// ...
	
	doSomething(martinsClass(designSetting1));
}


Liebe Gruesse,
		Joerg

-- 
"Immer wieder erstaunlich, wie lächerlich man sich doch machen kann und
sich dabei noch toll finden." 
                        - Hartmut Kraus, 19.3.2017 in de.soc.recht.misc

Ich lese meine Emails nicht, replies to Email bleiben also leider
ungelesen.

[toc] | [prev] | [next] | [standalone]


#38660

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2018-10-26 07:50 -0400
Message-ID<pquv2d$6p2$1@dont-email.me>
In reply to#38656
On 10/25/2018 8:37 PM, Martin Gregorie wrote:
> On Thu, 25 Oct 2018 20:08:54 -0400, Arne Vajhøj wrote:
> 
>> Enum achives the same 4 goals (except obviously the first half of #a -
>> not having to define an enum).
>>
> Sure, though being defined outside a class that is the only place its
> used (apart from when its supplied as a method argument) as we've been
> discussing does separate each constant definition and its documentation
> from the class definition and documentation

	public class Whatnot {
	    public static enum Style { LONG, SHORT };
	    ...
	    String method(Style style) { ... }
	}

	Whatnot what = new Whatnot();
	String thing = what.method(Whatnot.Style.SHORT);

>> And enum will be better/easier documented for method arguments.
>>
> Apart from the separation mentioned above. I see this as a disadvantage
> though you may not.

     "Better/easier" is a *dis*advantage?  Is this Opposite Day?

>> And enum is type safe while int constants are not.
>>
> AFAIK that is not relevant if the constant is defined as static final.

     Both Arne's and Martin's comments elude my understanding, so
I won't try to respond.

>> will be accepted by the compiler but have undefined semantics.
>>
> Agreed, but being basically a mildly paranoid C programmer I tend to
> validate all arguments, including those created with a #define (C) or as
> static final int (Java) and you really shouldn't be defining a constant
> unless its one of the above or part of an enum.

     Early mistake detection beats late misteak detectoin, every time.
Compile-time detection beats run-time detection.

> So far, it all looks a bit like swings and roundabouts to me except, of
> course, if your enum contains logic rather than being simply a list of
> constants.

     My scorecard shows Arne with three, Martin with nil, and one
undecided.

-- 
esosman@comcast-dot-net.invalid
Eight hundred seventeen days to go.

[toc] | [prev] | [next] | [standalone]


#38662

FromMartin Gregorie <martin@mydomain.invalid>
Date2018-10-26 19:33 +0000
Message-ID<pqvq6t$cah$1@news.albasani.net>
In reply to#38660
On Fri, 26 Oct 2018 07:50:34 -0400, Eric Sosman wrote:

>      My scorecard shows Arne with three, Martin with nil, and one
> undecided.
>
Fair enough. General ignorance of Enums is why I asked and I've learnt 
stuff from as a result.

I haven't (so far) used Enums and it wasn't obvious from the tutorial 
stuff that you can put a public Enum inside a class - rather the opposite 
in fact, since at one point it said that an enum declaration was at a 
similar language level to a class declaration, which is why I thought it 
could not be declared insire a class definition.

Thanks to Eric's example I now see that was an incorrect assumption: I'll 
use Enums that way in future: my main background is Assembler/COBOL/C in 
that order, so of course I instantly saw the equivalence between 

#define SHORT 1   or its assembler equivalent

and

public static final int ONE = 1;
 

-- 
Martin    | martin at
Gregorie  | gregorie dot org

[toc] | [prev] | [next] | [standalone]


#38663

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-10-26 13:13 -0700
Message-ID<7f0c5b7c-1c0d-4691-93bc-1a33942eefa1@googlegroups.com>
In reply to#38662
On Friday, October 26, 2018 at 3:34:00 PM UTC-4, Martin Gregorie wrote:
> On Fri, 26 Oct 2018 07:50:34 -0400, Eric Sosman wrote:
> 
> >      My scorecard shows Arne with three, Martin with nil, and one
> > undecided.
> >
> Fair enough. General ignorance of Enums is why I asked and I've learnt 
> stuff from as a result.
> 
> I haven't (so far) used Enums and it wasn't obvious from the tutorial 
> stuff that you can put a public Enum inside a class - rather the opposite 
> in fact, since at one point it said that an enum declaration was at a 
> similar language level to a class declaration, which is why I thought it 
> could not be declared insire a class definition.
> 
> Thanks to Eric's example I now see that was an incorrect assumption: I'll 
> use Enums that way in future: my main background is Assembler/COBOL/C in 
> that order, so of course I instantly saw the equivalence between 
> 
> #define SHORT 1   or its assembler equivalent
> 
> and
> 
> public static final int ONE = 1;
>  

Aye, it's literally that simple.  Most of my values are also just on public static final int because I wrote most of the API before enum was a thing, but my one enum looks like this.

public class MyInputControl extends JTextField {
     public static enum INPUT_STYLE {
          CHARACTER, DATE, NUMBER,
     }

[toc] | [prev] | [next] | [standalone]


#38664

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-10-26 20:58 -0400
Message-ID<pr0d83$r6t$1@gioia.aioe.org>
In reply to#38662
On 10/26/2018 3:33 PM, Martin Gregorie wrote:
> I haven't (so far) used Enums and it wasn't obvious from the tutorial
> stuff that you can put a public Enum inside a class - rather the opposite
> in fact, since at one point it said that an enum declaration was at a
> similar language level to a class declaration,

It is.

>                                        which is why I thought it
> could not be declared insire a class definition.

You can put a class declaration inside a class.

>                                                                 I'll
> use Enums that way in future: my main background is Assembler/COBOL/C in
> that order, so of course I instantly saw the equivalence between
> 
> #define SHORT 1   or its assembler equivalent
> 
> and
> 
> public static final int ONE = 1;

I will say that:

C                        Java

#define X 1              No equivalent
#define Y 2
#define Z 3

const int X = 1;         public static final int X = 1;
const int Y = 2;         public static final int Y = 2;
const int Z = 3;         public static final int Z = 3;

enum XYZ { X, Y, Z };    public enum XYZ { X, Y, Z }

Assuming ANSI C and Java >= 1.5.

Arne

[toc] | [prev] | [next] | [standalone]


#38667

FromMartin Gregorie <martin@mydomain.invalid>
Date2018-10-27 22:36 +0000
Message-ID<pr2pa5$sql$1@news.albasani.net>
In reply to#38664
On Fri, 26 Oct 2018 20:58:44 -0400, Arne Vajhøj wrote:

> On 10/26/2018 3:33 PM, Martin Gregorie wrote:
>> I haven't (so far) used Enums and it wasn't obvious from the tutorial
>> stuff that you can put a public Enum inside a class - rather the
>> opposite in fact, since at one point it said that an enum declaration
>> was at a similar language level to a class declaration,
> 
> It is.
> 
>>                                        which is why I thought it
>> could not be declared inside a class definition.
> 
> You can put a class declaration inside a class.
> 
Yes indeed, but as I found out it seems not so simple to access it from 
outside. The following shows how I wanted to declare and use a enum, i.e. 
as a direct a replacement for the set of public static final ints). 
Here's an SSCCE that shows the problem. 

public class EnumWrapper
{
   public enum MyEnum { ONE, TOO, TREE };

   public static void main(String args[])
   {
      for (MyEnum x: MyEnum.values())
         printVal(x);
   }

   public static void printVal(MyEnum v)
   {
      System.out.println("printval(" + v + ")");
   }      
}

This works as expected with the enum used inside its declaring class:
$ java EnumWrapper
printval(ONE)
printval(TOO)
printval(TREE)
 
BUT, I also want to use it as a parameter when calling a methods in the 
class where the enum is declared, IOW exactly how I'd use a public static 
final int declared in the class:

public class TestRun
{
   public static void main(String args[])
   {
      EnumWrapper ew = new EnumWrapper();

      ew.printval(MyEnum.ONE);
   }
}

... and this won't compile:

This works as expected if the enum is being used inside its declaring 
class:
$ javac TestRun.java 
TestRun.java:7: error: cannot find symbol
      ew.printval(MyEnum.ONE);
                  ^
  symbol:   variable MyEnum
  location: class TestRun
1 error

and, if I replace 'MyEnum' with "EnumWrapper", the name of the class,
it still fails to compile:
$ javac TestRun.java 
TestRun.java:7: error: cannot find symbol
      ew.printval(EnumWrapper.ONE);
                             ^
  symbol:   variable ONE
  location: class EnumWrapper
1 error

Moving the enum to a separate file containing nothing except a package 
name specifier and the public enum declaration obviously works, but is 
not what I want since it separates the constants in the declaration from 
the code that accepts them as method arguments.

I understood, or thought I did, from earlier parts of this thread that it 
should be possible to do what I want, i.e. declare a public enum within 
the class whose methods are controlled by the enum values. I've checked 
various sources on the interwebs including the Oracle tutorial, but 
didn't find anything there, so - what have I missed or misunderstood?


-- 
Martin    | martin at
Gregorie  | gregorie dot org

[toc] | [prev] | [next] | [standalone]


#38668

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-10-27 19:38 -0400
Message-ID<pr2sui$me8$1@gioia.aioe.org>
In reply to#38667
On 10/27/2018 6:36 PM, Martin Gregorie wrote:
> On Fri, 26 Oct 2018 20:58:44 -0400, Arne Vajhøj wrote:
>> On 10/26/2018 3:33 PM, Martin Gregorie wrote:
>>>                                         which is why I thought it
>>> could not be declared inside a class definition.
>>
>> You can put a class declaration inside a class.
>
> Yes indeed, but as I found out it seems not so simple to access it from
> outside. The following shows how I wanted to declare and use a enum, i.e.
> as a direct a replacement for the set of public static final ints).
> Here's an SSCCE that shows the problem.
> 
> public class EnumWrapper
> {
>     public enum MyEnum { ONE, TOO, TREE };

>     public static void printVal(MyEnum v)
>     {
>        System.out.println("printval(" + v + ")");
>     }
> }
> 
> This works as expected with the enum used inside its declaring class:

> BUT, I also want to use it as a parameter when calling a methods in the
> class where the enum is declared, IOW exactly how I'd use a public static
> final int declared in the class:
> 
> public class TestRun
> {
>     public static void main(String args[])
>     {
>        EnumWrapper ew = new EnumWrapper();
> 
>        ew.printval(MyEnum.ONE);
>     }
> }
> 
> ... and this won't compile:

 > and, if I replace 'MyEnum' with "EnumWrapper", the name of the class,
 > it still fails to compile:

Normal name rules aka same as for nested classes.

public class TestRun
{
    public static void main(String args[])
    {
       EnumWrapper ew = new EnumWrapper();
       ew.printVal(EnumWrapper.MyEnum.ONE);
    }
}

should work.

import EnumWrapper.MyEnum;

public class TestRun2
{
    public static void main(String args[])
    {
       EnumWrapper ew = new EnumWrapper();
       ew.printVal(MyEnum.ONE);
    }
}

should also work.

The enums full name is EnumWrapper.MyEnum so either
full name or an import to use short name.

(in real life there would also be a package, but ...)

Arne

[toc] | [prev] | [next] | [standalone]


#38669

FromMartin Gregorie <martin@mydomain.invalid>
Date2018-10-28 10:39 +0000
Message-ID<pr43lo$3rb$1@news.albasani.net>
In reply to#38668
On Sat, 27 Oct 2018 19:38:56 -0400, Arne Vajhøj wrote:

> public class TestRun {
>     public static void main(String args[])
>     {
>        EnumWrapper ew = new EnumWrapper();
>        ew.printVal(EnumWrapper.MyEnum.ONE);
>     }
> }
> 
> should work.
> 
No, just a compilation failure:

$ javac TestRun.java 
TestRun.java:7: error: cannot find symbol
      ew.printval(EnumWrapper.MyEnum.ONE);
        ^
  symbol:   method printval(MyEnum)
  location: variable ew of type EnumWrapper
1 error

The answer in both cases turns out to be to put the sources in a 
directory called 'enum_test' and add "package enum_test;" to the sources.

This allowed TestRun to compile and run while the less verbose and 
slightly modified TestRun2, with a second call to printVal(), now 
compiles and runs with an additional import statement: 

package enum_test;
import enum_test.EnumWrapper.*;
public class TestRun2
{
   public static void main(String args[])
   {
      EnumWrapper ew = new EnumWrapper();
      ew.printVal(MyEnum.ONE);
      ew.printVal(MyEnum.TREE);
   }
}
  
I can live with the additional import statement since it lets me put the 
enum where I want it.

Thanks for your help.


-- 
Martin    | martin at
Gregorie  | gregorie dot org

[toc] | [prev] | [next] | [standalone]


#38670

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2018-10-28 07:54 -0400
Message-ID<pr4829$15b$1@dont-email.me>
In reply to#38669
On 10/28/2018 6:39 AM, Martin Gregorie wrote:
> [...]
> No, just a compilation failure:
> 
> $ javac TestRun.java
> TestRun.java:7: error: cannot find symbol
>        ew.printval(EnumWrapper.MyEnum.ONE);
>          ^
>    symbol:   method printval(MyEnum)
>    location: variable ew of type EnumWrapper
> 1 error

     Try `printVal', with a capital `V'.

-- 
esosman@comcast-dot-net.invalid
Eight hundred fifteen days to go.

[toc] | [prev] | [next] | [standalone]


#38661

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-10-26 06:26 -0700
Message-ID<fef929a1-e6f6-450a-8f39-5d05fe1bcab7@googlegroups.com>
In reply to#38653
On Thursday, October 25, 2018 at 5:49:37 PM UTC-4, Eric Sosman wrote:
> 
>      Also, be careful to distinguish between "there are exactly two
> possibilities" and "I have thought of only two possibilities."  It
> is perhaps instructive that the example given would not work for the
> printer that sits on my desk at this moment, which has *five* modes
> for duplexing:
> 
>      One-sided
> 
>      Two-sided (automatic, flip on long axis)
> 
>      Two-sided (automatic, flip on short axis)
> 
>      Two-sided (manual, flip on long axis)
> 
>      Two-sided (manual, flip on short axis)
> 
>      (In the "automatic" modes the printer marks one side but doesn't
> spit the page out, then sucks it back in and does the second side.
> In the "manual" modes it prints and ejects all the back sides, then
> you re-insert the stack in the paper supply and it prints the formerly-
> blank fronts.  "Automatic" is more convenient, "Manual" can be faster
> for long documents.)
> 
>      Duplex-or-not is, as suggested, a Yes/No question -- but if the
> answer is Yes the answer is incomplete, lacking essential detail.
> A good API offers (relatively) straightforward ways to supply all
> the necessary information.

Well you're just full of booleans, they could be overloads.
setDuplex(boolean isDuplex)
setDuplex(boolean isDuplex, boolean flipShortSide)
setDuplex(boolean isDuplex, boolean flipShortSide, boolean auto)

Though a separate method for the not-so-obvious-boolean would be more readable, setFlipOnShortSide(boolean), with flip on long side being the default either way.

It is probably common that boolean options are linked ie calling setFlipOnShortSide() does nothing unless you call setDuplex(true).
I actually can't think of many good examples of true independent boolean parameter examples.  It seems more often boolean is used in the return value.

Then we have old school parameter, java.awt.font.TextAttribute is full of static final numeric values, and new school parameter ie javax.print.attribute.standard.Sides.  While the documentation for EnumSyntax does say an enum is just an integer, it does auto-validate at compile time, and you don't have to maintain a condition in every method:
if (passInValue < 1 or passInValue > 5) { throw new InvalidParameterException("parameter must be in range of 1 to 5"); }
or deal with stack trace errors.

Most parameters could actually be boolean but is it more or less readable?  Is it more or less work?
public class Person{
  private int gender = 0;
  public void setIsMale(boolean val) {
    gender = val == true ? 0 : 1;
  }
  public void setIsFemale(boolean val) {
    gender = val == true ? 1 : 0;
  }
  public void setIsBiGender(boolean val) {
    gender = val == true ? 2 : gender;
  }
}
Now if the parameters are self documenting and it is both possible to be both or neither you could use one method
public void setGender(boolean isMale, boolean isFemale)

Some APIs like to name everything arg1 with no javadoc...

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.java.programmer


csiph-web