Sistema de Tipos de Eiffel A Proposal for Making Eiffel Type-safe W. R. Cook ECOOP’87 Proceedings Cambridge University Press, 1989 DI UFPE Sistema de Tipos de Eiffel Sistema de tipos fortes Relação de subtipo ligado a hierarquia de herança Tipo Tipo simples: REAL, INTEGER Tipo classe: P[U1, ..., Un] Parâmetro Tipo DI UFPE formal dentro de uma classe genérica associação: like anchor Sistema de Tipos de Eiffel class Base feature base(n: Integer): Integer is do Result := n * 2 end; end class Extra inherit Base feature extra(n: Integer): Integer is do Result := n * n end; end DI UFPE Sistema de Tipos de Eiffel DI UFPE Conformidade de tipos: relação de subtipo Y está em conformidade com X X e Y são idênticos X e Y são classes X não é genérica, e Y é subclasse direta de X X é da forma P[U1, ..., Un] e Y é subclasse de P[V1, ..., Vn] , onde Vi está em conformidade com Ui Y é da forma like anchor, e o tipo de anchor está em conformidade com X Há um tipo Z tal que Y está em conformidade com Z e Z está em conformidade com X Sistema de Tipos de Eiffel Em resumo Y está em conformidade com X se Y herda de X Logo, o mecanismo de herança Deve garantir que objetos de uma subclasse podem ser usados quando objetos da superclasse forem esperados Modificações que podem ser feitas em uma subclasse Adição DI UFPE de atributos Modificação da implementação dos métodos Modificação de tipos de atributos e métodos Sistema de Tipos de Eiffel Regra de redefinição de tipo Um atributo, um resultado de função ou o argumento de um método pode ser redeclarado com um novo tipo em uma subclasse, desde que o novo tipo esteja em conformidade com o tipo original. DI UFPE Redefinição de Tipos de Atributos class P1 feature a: Base; setup is local x: Base; do x.Create; a := x; end; end DI UFPE class C1 inherit P1 redefine a feature a: Extra; problem: Integer is do setup; Result := a.extra(2); end; end Solução: uso de tipo associação Redefinição de Tipos de Argumentos class P2 feature get(arg: Base): Integer is do Result := arg.base(1) end; end class C2 inherit P2 redefine get feature get(arg: Extra): Integer is do Result := arg.extra(2) end; end DI UFPE Redefinição de Tipos de Argumentos Problema: C2 está em conformidade com P2 local a: Base; v: P2; b: C2 do a.Create; b.Create; v := b; v.get(a); end DI UFPE Redefinição de Tipo de Argumento Solução O resultado e o argumento de um método pode ser redeclarado, desde que Resultado: esteja em conformidade com o original Argumento: o original esteja em conformidade com o novo tipo Problema Redefinição DI UFPE de tipos se torna praticamente inútil Métodos Declarados por Associação Outro problema associado a nova regra de redefinição Impacto no uso de tipos associação na declaração de argumentos Proibir o uso de tipos associação na definição de argumentos? Solução Quando a âncora de um tipo de um argumento é redeclarada, conformidade não é mantida Mas DI UFPE outros problemas surgem Mais um Problema class P3 feature base ... get(arg: like Current): Integer is do Result := arg.base(1) end; not_assoc(arg: P3): Integer is local x: P3; do x.Create; Result := arg.get(x); end; subvert(arg: like Current): Integer is do Result := not_assoc(arg); end; end DI UFPE Mais um Problema class C3 inherit P3 redefine get feature extra ... get(arg: like Current): Integer is do Result := arg.extra(2) end; end c: C3 c.subvert(c) DI UFPE Conformidade de Tipos Genéricos DI UFPE Regras atuais Não consideram que P[V] está em conformidade com P[U] quando V está em conformidade com U Novas regras Y está em conformidade com X X e Y são classes Y é subclasse direta de X X é da forma P[U1, ..., Un] e Y é da forma P[V1, ..., Vn] , onde Vi está em conformidade com Ui Conformidade de Tipos Genéricos class Cell[T] feature info: T; change_info(x : T) is do info := x end; end local x: Base; a: Cell[Base]; b: Cell[Extra]; do x.Create; b.Create; a:= b; a.change_info(x); b.info.extra(4); end DI UFPE Conformidade de Tipos Genéricos Solução: identificar contextos de usos de parâmetros Parâmetro covariante Tipos de atributos e saídas de métodos Parâmetro contravariante Tipos de argumentos de métodos Parâmetro bivariante Tipos de atributos, saídas e argumentos de métodos DI UFPE Conformidade de Tipos Genéricos DI UFPE Nova regra X e Y são classes, X é da forma P[U1, ..., Un] e Y é da forma P[V1, ..., Vn] , onde para cada para parâmetro Ti se Ti é covariante Vi está em conformidade com Ui se Ti é contravariante Ui está em conformidade com Vi se Ti é bivariante Vi é igual a Ui Tipo Associação Regra de conformidade forte demais Y é da forma like anchor, e o tipo de anchor está em conformidade com X DI UFPE Se X é da forma like left-anchor, então Y tem que ser igual Tipo Associação Porque... class C feature left-anchor: U; x: like left-anchor; y: T; ... x := y; Se T estiver em conformidade com U? end DI UFPE Tipo Associação class D inherit C left-anchor: U’; ... x := y end DI UFPE Pode ser inválido se T não estiver em conformidade com U’ Tipo Associação Mas ... class C feature left-anchor: U; x: like left-anchor; ... x := left-anchor; end DI UFPE Deveria ser válido Tipo Associação Além disso... class C feature a: T; m(arg: like a) ... end local c: C; b: T; do c.m(b); DI UFPE Solução: atributos de tipo Inválido Mecanismo de Exportação Independência entre exportação e herança é falsa local e: Extra; Hidden feature base v: Base; do v := e; Result := v.base; end DI UFPE Solução: desistir Conclusão Recomendações Substitua Elimine Inverta tipo associação com atributos de tipo redefinição de tipo de atributo regra de redefinição de argumento de método Desconecte a relação de conformidade da relação de herança Considere DI UFPE as cláusulas ‘export’ cumulativas Subclasses não são necessariamente subtipos Resposta de Meyer “Catcalls” polimórficas são proibidas “Catcall”: método que tem redefinição que pode causar problemas devido a sua remoção da lista de exportação ou novo tipo de argumento Chamada polimórfica: o tipo do objeto alvo pode variar Está a esquerda de atribuições É um argumento de método DI UFPE