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 ofmé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 longvalor, 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 longe todos os outros construtores usam int), você pode se safar disso.
Se você analisasse o código que chama um LocalDateconstrutor 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 ofEpochDayentanto, sinaliza uma clara diferença de unidades e intenção. Da mesma forma, LocalDate.ofYearDaysinaliza que o monthparâmetro comum está sendo ignorado e que o parâmetro day, embora ainda intseja um, dayOfYearnã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 . LocalDatepoderia fornecer um construtor Java padrão, além de, ou no lugar de, seus dois ofmétodos. Mas com que finalidade? Ele ainda precisa ofEpochDaye ofDayYearpara esses casos de uso. Algumas classes fornecem construtores e o equivalente a ofXYZmétodos - por exemplo, ambos Float('3.14')e Float.parseFloat('3.14')existem. Mas se você precisa de ofXYZconstrutores 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 LocalDatemétodos são construtores. Existem grandes grupos de sete de métodos que constroem novos casos (respectivamente, o at, from, minus, of, parse,pluse withprefixos). Dos LocalDatemais 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.