0

If I code like this:

Period wrong = Period.ofYears(1).ofWeeks(1);

It gives output of P7D.

By the implementation of Period class we know that all of____() methods are static.

But if you to do same chaining with DateTime class:

LocalDate date = LocalDate.of(2020, Month.JANUARY, 20);
LocalTime time = LocalTime.of(5, 15);
LocalDateTime dateTime = LocalDateTime.of(date, time)
  .minusDays(1).minusHours(10).minusSeconds(30);

All minus___() and plus___() methods are instance methods in LocalDateTime class.

Question: why is method chaining not allowed for the Period class?

Why the Period class isn't supporting that?

How the internal assignment is going on ?

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Hasnain Ali Bohra
  • 2,130
  • 2
  • 11
  • 25
  • 2
    You can not chain the of() methods – Jens Jul 28 '17 at 09:36
  • You can chain calls of method from the Persion class if you would use the proper methods ... – Tom Jul 28 '17 at 09:41
  • Maybe I am too naive today, but I dont think you deserve all these downvotes coming in ... yes, it seems naive to chain static calls, but you clearly ask "why" the Period class isn't supporting that. – GhostCat Jul 28 '17 at 09:46
  • 1
    @GhostCat And can you answer that "why"? The only group of people telling OP why these methods are all static are the designers/developers of that class. We can just guess. – Tom Jul 28 '17 at 09:55
  • @Tom I think I gave that answer. It is because ofA().ofB() doesn't carry a reasonable semantic. Compare that to ofA().plus(ofB()) - like the other answer is showing! – GhostCat Jul 28 '17 at 09:58
  • 1
    @GhostCat You've explained how these methods work and why OPs code doesn't work, but you haven't explained _why_ the designers added these methods and not such builder methods like `LocalDateTime` has. That can only be answered by the designers themselves :/. We're interpreting OPs "why" differently. – Tom Jul 28 '17 at 10:53
  • 1
    The creation part in Period as well as LocalDateTime/LocalDate etc. is handled in the similar way by means of static factory methods. You can write `LocalDate today = LocalDate.of(2017, 06, 02).of(2018, 8, 31);` and this will ultimately give you the date 2018-08-31. But what you are trying to do here won't make sense. The purpose of chaining is to enable the manipulations to the date/time in a fluent easily readable and understandable way. So, even in Period class,you can write `Period.ofYears(1).plusYears(2)` which results in a Period of 3 years. – Pallavi Sonal Jul 28 '17 at 11:26
  • 2
    Of course it's allowed: `Period.ofYears(10).plusMonths(1).plusDays(1).minusYears(3)...` Only the chaining of the `of__()` methods are not *"allowed"* for all the reasons already explained (semantics, the way they were designed to work, etc). But I agree with @Tom that only the API designers can tell us **why**. For us, the only answer we can provide to *"Why?"* is *"Because it was designed to work like that"*. Basically, `of` creates a new object, `plus` and `minus` methods can be chained. Why? Because the API creators decided to do it this way. –  Jul 28 '17 at 12:40
  • You can't chain static methods, period. And you _have_ to have static methods to start, basically, or a constructor. There's no way for any class to be able to chain the initial factory methods, only instance methods like `plusYears` etc, which is exactly what Period does. There's no way it _could_ have been designed the way you're describing other than what they actually did. – Louis Wasserman Jul 28 '17 at 17:34
  • You can do that instead: LocalDate d = LocalDate.parse("2020-01-01").minusMonths(1).minusDays(1).plusYears(10); System.out.println(d); – Java bee Dec 14 '20 at 14:59

3 Answers3

13

You are not chaining calls in your first example.

Period wrong = Period.ofYears(1).ofWeeks(1);

is the same as:

Period wrong = Period.ofWeeks(1);

In other words: the object returned by ofYears() does not affect the result of ofWeeks() and it's year value will be discarded. You are invoking the static method ofWeeks(). What you are doing there is not a fluent call chain.

And any decent IDE should warn you about doing so. The reason is simple: this "chaining" simply doesn't make sense!

The ofXyz() calls create a new Period object for you. That object is done and created. What should be the semenatics of chaining another ofXyz() call onto the existing period?

In other words: you can't chain ofXyz() calls because there is no clear way to express the semantics that such a chain should have!

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • I know this. My question is Why is it so ? – Hasnain Ali Bohra Jul 28 '17 at 09:37
  • 4
    @HasnainAliBohra Why is it so: Because that is just how these methods are designed to work. – Jesper Jul 28 '17 at 09:39
  • The `of` methods are static factory methods. Factory methods create a new object, they are static so have no previous state. The `with`, `plus` and `min` methods can be chained, since Period is immutable, a new object is returned while the new state is passed to the new object. So there is a difference between factories (the creation of objects) and an object being immutable. A static factory method (of) cannot have the same name as a non static method, so one is called `of` and the others starts with `with`, `plus` or `min`... – Douma Dec 26 '20 at 00:47
9

Period allows to chain methods have a look to instance methods plus, plusDays etc.

Period.ofYears(1).plus(Period.ofWeeks(1));
Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36
6

By the implementation of Period class we know that all of____ () methods are static.

Exactly.

So Period.ofYears(1) will give you an instance of Period but you are not using this instance for anything useful.

Instead, you are invoking the static method ofWeeks on this instance. Doing this will give you a compiler warning, precisely for the reason you've demonstrated - it looks misleading.

This question talks a bit about this behaviour: Why isn't calling a static method by way of an instance an error for the Java compiler? In my opinion it's a poor design choice of Java to be able to do this at all.

If you to do same chaining with DateTime Class ... all minus___() and plus___() methods are instance methods in LocalDateTime Class

These methods still exist in Period, except for plusWeeks. Instead, you can do this:

// 1 year and 5 weeks
Period.ofYears(1).plusDays(5 * 7);
Michael
  • 41,989
  • 11
  • 82
  • 128
  • Or use `Period.ofWeeks(1).plusYears(1);`. – Tom Jul 28 '17 at 09:57
  • 2
    @Tom I think there's value in keeping things in descending size order. It's feels slightly unnatural to read it as "a week and a year". But still, a good alternative. – Michael Jul 28 '17 at 09:59