Não projetei ou escrevi a API de data e hora do Java, por isso não posso dizer definitivamente "por que eles fizeram dessa maneira". No entanto, posso sugerir dois motivos principais para que eles façam dessa maneira:
- Poder expressivo
- Forma paralela
Primeiro, considere o contexto: o código de datas e hora do Java é um pacote grande e complexo que trata de um assunto muito complicado. Por mais comum que seja a "hora", a implementação do conceito envolve dezenas de interpretações e formatos, com variações entre locais geográficos (fusos horários), idiomas, sistemas de calendário, resoluções de relógio, escalas de tempo, escalas de tempo, representações numéricas, fontes de dados e intervalos. Deltas corretivos (por exemplo, anos bissextos / dias) são comuns e podem ser inseridos irregularmente a qualquer momento (segundos bissextos). No entanto, o pacote é um recurso essencial, provavelmente usado amplamente, e espera-se que ele lide com todas essas variações de maneira correta e precisa. É uma tarefa difícil. O resultado, sem surpresa, é uma API complexa, incluindo muitas classes, cada uma com muitos métodos.
Agora, por que usar of
métodos em vez de um construtor de classe "regular"? Por exemplo , por que LocalDate.of(...)
, LocalDate.ofEpochDay(...)
e LocalDate.ofYearDay(...)
não apenas um punhado de new LocalDate(...)
chamadas?
Primeiro, poder expressivo : métodos nomeados individuais expressam a intenção da construção e a forma dos dados que estão sendo consumidos.
Suponha por um momento que a sobrecarga do método Java seja suficiente para permitir a variedade de construtores que você deseja. (Sem entrar em uma discussão sobre o recurso de linguagem sobre digitação de patos e envio único versus dinâmico versus envio múltiplo , vou apenas dizer: às vezes isso é verdade, às vezes não. Por enquanto, apenas assuma que não há nenhuma limitação técnica.)
Pode ser possível para a documentação do construtor declarar "quando passado apenas um único long
valor, esse valor é interpretado como uma contagem de dias da época, não um ano". Se os tipos de dados de baixo nível passados para os outros construtores forem diferentes (por exemplo, apenas o caso da época usa long
e todos os outros construtores usam int
), você pode se safar disso.
Se você analisasse o código que chama um LocalDate
construtor com um único long
, seria muito semelhante ao código no qual um ano é passado, especialmente com a passagem de um ano, sem dúvida o caso mais comum. Ter esse construtor comum pode ser possível, mas não necessariamente leva a uma grande clareza.
A API explicitamente chamando no ofEpochDay
entanto, sinaliza uma clara diferença de unidades e intenção. Da mesma forma, LocalDate.ofYearDay
sinaliza que o month
parâmetro comum está sendo ignorado e que o parâmetro day, embora ainda int
seja um, dayOfYear
não é um dayOfMonth
. Os métodos explícitos do construtor visam expressar o que está acontecendo com maior clareza.
Linguagens dinamicamente e tipadas como pato, como Python e JavaScript, têm outros meios para sinalizar interpretações alternativas (por exemplo, parâmetros opcionais e valores de sentinela fora da banda ), mas mesmo os desenvolvedores de Python e JS costumam usar nomes de métodos distintos para sinalizar interpretações diferentes. É ainda mais comum em Java, dadas as restrições técnicas (é uma linguagem de envio único estaticamente) e as convenções / expressões culturais.
Segunda forma paralela . LocalDate
poderia fornecer um construtor Java padrão, além de, ou no lugar de, seus dois of
métodos. Mas com que finalidade? Ele ainda precisa ofEpochDay
e ofDayYear
para esses casos de uso. Algumas classes fornecem construtores e o equivalente a ofXYZ
métodos - por exemplo, ambos Float('3.14')
e Float.parseFloat('3.14')
existem. Mas se você precisa de ofXYZ
construtores para algumas coisas, por que não usá-las o tempo todo? Isso é mais simples, mais regular e mais paralelo. Como um tipo imutável, a maioria dos LocalDate
métodos são construtores. Existem grandes grupos de sete de métodos que constroem novos casos (respectivamente, o at
, from
, minus
, of
, parse
,plus
e with
prefixos). Dos LocalDate
mais de 60 métodos, 35+ são construtores de fato . Apenas dois deles podem ser facilmente convertidos em construtores padrão baseados em classe. Realmente faz sentido, para casos especiais, aqueles 2 de uma maneira não paralela a todos os outros? O código do cliente usando esses dois construtores de casos especiais seria notavelmente mais claro ou mais simples? Provavelmente não. Pode até tornar o código do cliente mais variado e menos direto.