Scopes

Figure 262. Circle and variable scopes Slide presentation Create comment in forum

Figure 263. Documenting classes and methods Slide presentation Create comment in forum
/** Representing circles.
 */
public class Circle {
  private double radius;

  /** Creating a circle.
   *  @param r representing the circle's radius
   */
  public Circle(double r) {
    radius = r;
  }
  public double getDiameter() {
    return 2 * radius;
  }
}

Figure 264. Generated Javadoc Slide presentation Create comment in forum

Figure 265. Refactoring «r» ⇒ «radius» Slide presentation Create comment in forum

Figure 266. Scope assignment problem Slide presentation Create comment in forum
/** Representing circles.
 */
public class Circle {
  private double radius;

  /** Creating a circle.
   *  @param radius Circle's size
   */
  public Circle(double radius) {
    radius = radius; // Warning: Variable 'radius' is assigned to itself.
  }
  public double getDiameter() {
    return 2 * radius;
  }
}

Figure 267. this overriding method scope Slide presentation Create comment in forum

exercise No. 95

Turning seconds into weeks part 2 Create comment in forum

Q:

This is a follow-up exercise to Turning seconds into weeks implementing a corresponding Timeperiod class. Consider the subsequent example demonstrating both its constructor and toString() method:

final Timeperiod t = new Timeperiod(112223);
System.out.println(92 + " seconds are equal to " + t);
92 seconds are equal to 1 day, 7 hours, 10 minutes and 23 seconds

Since the toString() method may not be called at all it shall be implemented on demand. Tip: create a suitable attribute being null initially. If toString() is being called, first check for null and initialize it on demand only.

Furthermore the individual weeks, days, hours, minutes and seconds should be implemented as readonly values using final:

final Timeperiod t = new Timeperiod(2310983);
System.out.print("weeks = "     + t.weeks +
                 "\ndays = "    + t.days +
                 "\nhours = "   + t.hours +
                 "\nminutes = " + t.minutes +
                 "\nseconds = " + t.seconds);
weeks = 3
days = 5
hours = 17
minutes = 56
seconds = 23

In other words: The Timeperiod class should be implemented as an immutable. Thus once a Timeperiod instance has been created it shall be impossible to alter the instance i.e. changing its state.

Use the following tests to check your implementation:

public class TimeperiodTest {

    // Helper methods for real tests.
    static void assertPeriodEqualImplement(final int expectedSeconds,
                          final int expectedMinutes,
                          final int expectedHours,
                          final int expectedDays,
                          final int expectedWeeks,
                          final String expectedToString,
                          final Timeperiod period) {
        Assert.assertEquals(expectedSeconds, period.seconds);
        Assert.assertEquals(expectedMinutes, period.minutes);
        Assert.assertEquals(expectedHours, period.hours);
        Assert.assertEquals(expectedDays, period.days);
        Assert.assertEquals(expectedWeeks, period.weeks);

        Assert.assertEquals(expectedToString, period.toString());

    }

    static void assertPeriodEqual(final int expectedSeconds,
                          final int expectedMinutes,
                          final int expectedHours,
                          final int expectedDays,
                          final int expectedWeeks,
                          final String expectedToString,
                          final Timeperiod period) {

        // Testing period in question
        assertPeriodEqualImplement(
                expectedSeconds, expectedMinutes, expectedHours, expectedDays, expectedWeeks, expectedToString,
                period);

        // Also testing copy constructor
        assertPeriodEqualImplement(
                expectedSeconds, expectedMinutes, expectedHours, expectedDays, expectedWeeks, expectedToString,
                new Timeperiod(period));
    }

    /**
     * Test constructor zero seconds.
     */
        @Test
        public void testZero() {
            assertPeriodEqual(
                    0,0,0,0,0,
                    "0 seconds",
                    new Timeperiod(0));
        }

    @Test
    public void testMinute() {
        assertPeriodEqual(0,1,0,0,0,
                "1 minute and 0 seconds",
                new Timeperiod(60));
        assertPeriodEqual(50,0,0,0,0,
                "50 seconds",
                new Timeperiod(50));
        assertPeriodEqual(12,1,0,0,0,
                "1 minute and 12 seconds",
                new Timeperiod(72));
        assertPeriodEqual(2,5,0,0,0,
                "5 minutes and 2 seconds",
                new Timeperiod(302));
    }

    @Test
    public void testHour() {
        assertPeriodEqual(0,0,2,0,0,
                "2 hours, 0 minutes and 0 seconds",
                new Timeperiod(7200));
        assertPeriodEqual(59,59,0,0,0,
                "59 minutes and 59 seconds",
                new Timeperiod(3599));
        assertPeriodEqual(40,1,1,0,0,
                "1 hour, 1 minute and 40 seconds",
                new Timeperiod(3700));
    }

    @Test
    public void testVarious() {
        assertPeriodEqual(1,3,4,1,6,
                "6 weeks, 1 day, 4 hours, 3 minutes and 1 second",
                new Timeperiod(3729781));

        assertPeriodEqual(23,56,17,5,3,
                "3 weeks, 5 days, 17 hours, 56 minutes and 23 seconds",
                new Timeperiod(2310983));
    }
}

A:

Our implementation basically reads:

public Timeperiod(final Timeperiod timeperiod) {

    public final int seconds, minutes, hours, days, weeks;
    // Constructors and toString() ...

}

The final modifier ensures instances to be immutable requiring all values to be set within any constructor. We thus decompose the desired number of seconds into weeks, days, hours, minutes and remaining seconds:

public Timeperiod(int seconds) {

  weeks = seconds / SECONDS_PER_WEEK;
  seconds = seconds % SECONDS_PER_WEEK;        // remaining seconds without weeks

  days = seconds / SECONDS_PER_DAY;
  seconds %= SECONDS_PER_DAY;                  // remaining seconds without days

  hours = seconds / SECONDS_PER_HOUR;
  seconds %= SECONDS_PER_HOUR;                 // remaining seconds without minutes

  minutes = seconds / SECONDS_PER_MINUTE;
  this.seconds = seconds % SECONDS_PER_MINUTE; // remaining seconds
}

Notice the this.seconds qualification being required to disambiguate the constructor parameter variable Timeperiod(int seconds) from the instance member variable Timeperiod.seconds.