sealed interface I permits A, B, C { }
final class A implements I { }
final class B implements I { }
record C(int j) implements I { } // Implicitly final
record Box(I i) { }
int testExhaustiveRecordPatterns(Box b) {
return switch (b) { // Exhaustive!
case Box(A a) -> 0;
case Box(B b) -> 1;
case Box(C c) -> 2;
};
}
Este é um exemplo que aparece na especificação da linguagem Java 22 (14.11.1.1) .
Posteriormente, a especificação fornece algumas explicações:
Determinar se esse bloco de switch é exaustivo requer a análise da combinação dos padrões de registro. O conjunto que contém o padrão de registro
Box(I i)
cobre o tipoBox
, e assim o conjunto que contém os padrõesBox(A a)
,Box(B b)
, eBox(C c)
pode ser reescrito para o conjunto que contém o padrãoBox(I i)
. Isso ocorre porque o conjunto que contém os padrõesA a
,B b
,C c
reduz-se ao padrãoI i
(porque o mesmo conjunto cobre o tipoI
), e assim o conjunto que contém os padrõesBox(A a)
,Box(B b)
,Box(C c)
reduz-se ao padrãoBox(I i)
.
No entanto, ainda não é detalhado o suficiente para mim. Posso ver que essas regras devem ser citadas ao determinar se o bloco switch é exaustivo (Algumas regras relevantes):
O bloco switch de uma expressão switch ou instrução switch é exaustivo para uma expressão seletora
e
se um dos seguintes casos se aplicar:• O conjunto que contém todas as constantes de caso e padrões de caso que aparecem em um rótulo de caso desprotegido (conhecidos coletivamente como elementos de caso ) associado ao bloco switch não é vazio e cobre o tipo da expressão do seletor
e
.
Um conjunto de elementos de caso,
P
, cobre um tipoT
se um dos seguintes casos se aplicar:• O tipo
T
nomeia uma classe selada abstrata ou interface seladaC
e para cada subclasse ou subinterface direta permitidaD
deC
, uma das duas condições a seguir é válida:
- Não existe um tipo que nomeie
D
e seja um subtipo deT
, ou- Existe um tipo
U
que nomeiaD
e é um subtipo deT
, eP
abrangeU
.•
P
reescreve para um conjuntoQ
eQ
cobreT
.
Um conjunto de elementos de caso,
P
, é reescrito no conjuntoQ
, se um subconjunto deP
for reduzido a um >padrãop
, eQ
consiste nos elementos restantes deP
junto com o padrãop
.Um conjunto não vazio de padrões,
RP
, reduz-se a um único padrãorp
se uma das seguintes condições for válida:–
RP
abrange algum tipoU
erp
é um padrão de tipo do tipoU
.–
RP
consiste em padrões de registro cujos tipos apagam todos para a mesma classe de registroR
comk
(k≥1) componentes e há um componente distintocr
(1≤r≤k) deR
tal forma que para cada outro componenteci
(1≤i≤k, i≠r) o conjunto contendo os padrões de componentes dos padrões de registro correspondentes ao componenteci
é equivalente a um único padrãoqi
, o conjunto contendo os padrões de componentes dos padrões de registro correspondentes ao componentecr
reduz-se a um único padrãoq
erp
é o padrão de registro do tipoR
com uma lista de padrões consistindo nos padrõesq1, ..., qr-1, q, qr+1, ..., qk
.Um conjunto não vazio de padrões EP é equivalente a um único padrão
ep
se uma das seguintes condições for válida: ›EP
consiste em padrões de tipo cujos tipos têm todos a mesma eliminaçãoT
, eep
é um padrão de tipo do tipoT
. ›EP
consiste em padrões de registro cujos tipos apagam todos para a mesma classe de registroR
comk
(k≥1) componentes e para cada componente de registro o conjunto contendo os padrões de componentes correspondentes dos padrões de registro é equivalente a um único padrãoqj
(1≤j≤k), eep
é o padrão de registro do tipoR
com uma lista de padrões de componentes consistindo nos padrões de componentesq1,...qk
.
No entanto, tenho alguma dificuldade em entender essas regras, especialmente as partes em negrito. Por exemplo,O que significa " from the record patterns matching to component ci "," from the record patterns matching to the component cr "?Para ser mais preciso, acho que não entendi bem o significado de " matching to " aqui. De acordo com as explicações na especificação, acho que a frase "This is because the set containing the patterns A a
, B b
, C c
reduces to the pattern I i
" deve ter usado as regras na parte em negrito.No entanto, não consigo descobrir como A a
, B b
, C c
surgiu.
Você poderia me ajudar a analisar os regulamentos na especificação em combinação com os exemplos?Sei que não é uma tarefa fácil. Obrigado por ler e responder.
"Corresponde a" significa apenas o que normalmente significa em inglês. X "corresponde a" Y significa que X corresponde a Y de alguma forma. Um padrão corresponde a um componente de registro significa que ele está tentando corresponder a esse componente de registro.
Considere o registro
record R(int x, int y, int z) {}
e o padrãoR(int a, int b, int c)
. Podemos dizer:int a
corresponde ao primeiro componentex
int b
corresponde ao segundo componentey
int c
corresponde ao terceiro componentez
Aqui mostrarei que este conjunto de padrões (RP):
Box(A a)
Box(B b)
Box(C c)
reduz-se ao padrão
Box(I i)
("rp").Aplicando a regra citada, RP consiste em padrões de registro que nomeiam o registro
Box
, que tem apenas um componente, então k=1. Podemos mostrar que o único componente que há neste registro satisfaz as condições de ser o "componente distinto" cr. ou seja, mostre que r=1cr precisa satisfazer duas condições:
A primeira condição é vagamente verdadeira, pois não há outros componentes.
"O conjunto que contém os padrões de componentes dos padrões de registro correspondentes ao componente cr" refere-se ao conjunto:
A a
B b
C c
Todos esses são "padrões de registro" RP e todos eles "correspondem" ao único componente do registro (que é cr).
Aqui está outro exemplo: o padrão
Y y
no padrão de registroR(X x, Y y, Z z)
corresponde ao segundo componente deR
.É trivial mostrar que
A a
,B b
eC c
cobreI
. PortantoI i
é nosso "q".Agora vamos encontrar rp,
k=1 neste caso, então a lista de padrões consiste apenas em q. Concluímos que rp é
Box(I i)
.A primeira condição para cr é variadamente verdadeira neste caso, mas vamos supor que
Box
tem dois componentes de registro, ambos do tipoI
. E suponha que RP tem:Box(A a, I i)
Box(B b, I i)
Box(C c, I i)
Agora cr é o primeiro componente, e o único ci é o segundo componente. Os padrões que "correspondem" ao segundo componente são os três
I i
, e obviamente todos eles são equivalentes entre si. Então isso vai reduzir paraBox(I i1, I i2)
.Por fim, vamos considerar se o switch possui os seguintes casos:
Box(A a, A a)
Box(B b, A a)
Box(C c, A a)
Box(A a, B b)
Box(B b, B b)
Box(C c, B b)
Box(A a, C c)
Box(B b, C c)
Box(C c, C c)
Isso também é exaustivo, mas não podemos reduzir todos os 9 padrões de uma vez, porque não há componente que satisfaça essas duas condições para cr. Podemos reescrever esse conjunto 4 vezes para chegar a
Box(I i1, I i2)
, cada vez reduzindo um subconjunto dos padrões.Primeiro, reduzimos os primeiros 3 padrões para
Box(I i, A a)
, os próximos 3 padrões paraBox(I i, B b)
, e os últimos três padrões paraBox(I i, C c)
. Finalmente, reduzimosBox(I i, A a)
,Box(I i, B b)
,Box(I i, C c)
paraBox(I i1, I i2)
.