SlideShare uma empresa Scribd logo
1 de 36
8
           Sistemas de Tipos

 Polimorfismo de inclusão.

 Polimorfismo paramétrico.

 Sobrecarga.

 Conversões de tipos.

 Notas de implementação.
                              7-1
Polimorfismo de inclusão (1)

 Polimorfismo de inclusão é um sistema de tipo no qual um
  tipo pode ter subtipos, que herdam as operações daquele
  tipo
   • Conceito-chave das linguagem orientadas a objetos

 Tipos e subtipos
   • Um tipo T é um conjunto de valores equipado com operações
   • Um subtipo de T é um subconjunto dos valores de T equipado com
     as mesmas operações de T
       – Todo valor do subtipo também é valor do tipo T, podendo ser usado no
         contexto onde um valor do tipo T é esperado
       – O conceito de subtipos é uma idéia útil e comum em programação
                                                          7-2
Exemplo: tipos primitivos e subtipos em Ada

   Declarações em Ada definindo subtipos de Integer
     •   subtype Natural is Integer range 0 .. Integer'last;
         subtype Small is Integer range -3 .. +3;

     • Conjuntos de valores correspondentes
          – Natural = {0, 1, 2, 3, 4, 5, 6, ...}
            Small = {-3, -2, -1, 0, +1, +2, +3}

     • Variáveis                          i := n;      Requer verificação em
          – i: Integer;                   i := s;      tempo de execução
            n: Natural;
            s: Small;
                                          n := i; n := s;
                                          s := i; s := n:



                                                         7-3
Exemplo: tipos e subtipo de registros
     discriminados em Ada (1)
 Declaração de registro discriminado em Ada
   •   type Form is (pointy, circular, rectangular);
       type Figure (f: Form := pointy) is
         record
           x, y: Float;
           case f is
             when pointy => null;
             when circular => r: Float;
             when rectangular => h, w: Float;
           end case;
         end record;

         subtype Point is Figure(pointy);
         subtype Circle is Figure(circular);
         subtype Rectangle is Figure(rectangular);

   • Conjuntos de valores
        – Form = {pointy, circular, rectangular}
          Figure = pointy(Float × Float) + circular(Float × Float × Float) +
                 rectangular(Float × Float × Float × Float)
                                                                 7-4
Exemplo: tipos e subtipo de registros
     discriminados em Ada (2)
 Conjunto de valores dos subtipos
        – Point = pointy(Float × Float)
          Circle = circular(Float × Float × Float)
          Rectangle = rectangular(Float × Float × Float × Float)

 Exemplos de variáveis
   •   diagram: array (...) of Figure;
       frame: Rectangle;
       cursor: Point;




                                                               7-5
Polimorfismo de inclusão (2)

 Em linguagens de programação que suportam subtipos, não
  é possível estabelecer univocamente o subtipo de um valor




 Propriedades gerais dos subtipos
   • Condição necessária para S ser um subtipo de T: S ⊆ T
   • O tipo T é equipado com operações que são aplicáveis a todos os
     valores do tipo T
   • Todas essas operações também serão aplicáveis aos valores do
     subtipo S – S herda as perações de T

                                                      7-6
Polimorfismo de inclusão (3)

      Compatibilidade de tipos na presença de subtipos
            • V := E
tipo = T2                    tipo = T1
            • T1 é compatível com T2 se e somente se T1 e T2 têm valores em
              comum
                – Ou T1 é um subtipo de T2 ou T2 é um subtipo de T1 ou T1 e T2 são
                  subtipos de outro tipo qualquer
            • Casos de interesse quando T1 e T2 são compatíveis
                – T1 é um subtipo de T2: T1 pode ser usado com segurança num contexto
                  onde um valor de T2 é esperado – não precisa de verificação em tempo
                  de execução
                – T1 não é um subtipo de T2: valores do tipo T1 somente podem ser
                  usados após verificação em tempo de execução para determinar se ele
                  também é um valor do tipo T2                        7-7
Classes e subclasses

 Uma classe C é um conjunto de objetos equipados com
  operações
   • Cada objeto da classe C tem uma ou mais variáveis componentes e
     está equipada com métodos que acessam essas variáveis
   • Cada objeto de uma subclasse S de C herda todas as variáveis
     componentes dos objetos da classe C, podendo ter variáveis
     componentes adicionais
   • Cada objeto da classe S potencialmente herda todos os métodos
     dos objetos da classe C e pode ser equipada com métodos
     adicionais para acessar tais variáveis
   • Qualquer objeto de uma subclasse pode ser usado no contexto
     onde um objeto da classe C é esperado

 Subclasses não são o mesmo que subtipos em geral
                                            7-8
Exemplo: subclasses de Java
               como subtipos (1)
 Considere as classes
   •   class Point {
         protected double x, y;

           public void draw () {...}
       }


       class Circle extends Point {
         private double r;

           public void draw () {...}
       }


       class Rectangle extends Point {
         private double w, h;

           public void draw () {...}
       }


                                         7-9
Exemplo: subclasses de Java
           como subtipos (2)
 Conjuntos de valores das classes
       – Point = Point(Double × Double)
         Circle = Circle(Double × Double × Double)
         Rectangle = Rectangle(Double × Double × Double × Double)
   • Nota-se que Circle e Rectangle não são subtipos de Point
   • Mas são subtipos do tipo Point$ abaixo
       – Point$ = Point(Double × Double) +
                 Circle(Double × Double × Double) +
                 Rectangle(Double × Double × Double × Double)
                                  Point$




                                                         7-10
Exemplo: subclasses de Java
            como subtipos (3)
 Java permite que objetos de qualquer subclasse sejam
  tratados como objetos da superclasse
   •   Point p;
       ...
       p= new Point(3.0, 4.0);
       ...
       p= new Circle(3.0, 4.0, 5.0);

        – Variáveis do classe Point podem referenciar quaisquer valores do
          tipo Point$

   • Em geral, se C é uma classe, então C$ inclui não apenas os objetos
     da classe C, mas também os objetos de todas as subclasses de C
        – C$ é denominada de tipo de classe estendido (class-wide type)


                                                           7-11
Exemplo: extensibilidade em Java (1)

 Sejam as declarações considerando o exemplo anterior
   •   class Line extends Point {
         private double length, orientation;

           public void draw () { ... }
       }

       class Textbox extends Rectangle {
         private String text;

           public void draw () { ... }
       }

   • As definições acima não apenas definem os conjuntos de objetos
     das novas classes
           – Line = Line(Double × Double × Double)
             Textbox = Textbox(Double × Double × String)


                                                           7-12
Exemplo: extensibilidade em Java (2)

 • como também definem os tipos de classe estendidos abaixo
     – Point$ = Point(Double × Double) +
               Circle(Double × Double × Double) +
               Rectangle(Double × Double × Double × Double) +
               Line(Double × Double × Double) +
               Textbox(Double × Double × String)



     – Rectangle$ = Rectangle(Double × Double × Double × Double) +
                  Textbox(Double × Double × String)




                                                        7-13
Polimorfismo paramétrico (1)

 Polimorfismo paramétrico é um sistema de tipos que
  permite que se escrevam procedimentos polimórficos
   • Um procedimento polimórfico é aquele que pode operar
     uniformemente sobre argumentos de toda uma família de tipos

   • Um procedimento monomórfico é aquele que somente pode
     operar sobre argumentos de um tipo fixo

       – Uma função que computar o tamanho de uma lista de caracteres não
         pode ser aplicada a listas de inteiros, por exemplo



                                                               7-14
Polimorfismo paramétrico (2)

 Procedimentos polimórficos

   • Suportado naturalmente em Haskell

       – Basta que se declare o tipo da função utilizando variáveis de tipo, em
         vez de tipos específicos

            Uma variável de tipo é um identificador que denota um tipo de uma

              família de tipos

                » Letras romanas minúsculas em Haskell

                » Letras gregas nos exemplos do livro-texto (α, β, γ, ...)




                                                                         7-15
Exemplo: função polimórfica em Haskell (1)

   Função monomórfica em Haskell
     •   second (x: Int, y: Int) = y

     • Tipo da função
          – Integer × Integer → Integer
          – second(13, 21)   resulta no valor 21, mas a chamada
            second(13,   true) é ilegal, pois os tipos não casam


   A versão polimórfica desta função resolve este problema
     •   second (x: σ, y: τ) = y

     • Tipo da função
          – σ×τ→τ
          – σ e τ são variáveis de tipo, cada uma representação de um tipo
            arbitrário

                                                               7-16
Exemplo: função polimórfica em Haskell (2)

     • Agora, a chamada da função abaixo é legal
         – second(13, true)    resulta no valor true
         – O tipo da função determinado pelo casamento de tipos é o seguinte
              σ  Integer e τ  Boolean
              Substituíndo ambos no tipo σ × τ → τ, tem-se o tipo resultante da aplicação da
               função
              Integer × Boolean → Boolean

   Esta função polimórfica aceitas argumentos de muitos tipos, mas
    não quaisquer argumentos
     • Apenas pares da forma σ × τ
     • As chamadas abaixo são ilegais
         – second(13)
         – second(1978, 5, 5)
                                                                  7-17
Polimorfismo paramétrico (3)

 Um politipo deriva uma família de tipos e sempre possui
  uma ou mais variáveis de tipo
   ∀ σ × τ e σ × τ → τ são exemplos de politipos
   • Politipos derivam uma família de tipos pela substituição
     sistemática das variáveis de tipo por tipos
       – A família de tipos derivada por σ × τ → τ, incluem
            Integer × Boolean → Boolean
            String × String → String
       – mas não incluem
            Integer × Boolean → Integer
            Integer → Integer
            String × String × String → String


                                                          7-18
Exemplo: função polimórfica em Haskell

 Considere a seguinte função monomórfica em Haskell
   •   either (b: Bool) (x1: Char) (x2: Char) =
            if b then x1 else x2

   • O tipo dessa função é Boolean → Character → Character → Character
   •   translate (x: Char) =
           either (isspace x) x '*'

   • Nota-se que o tipo do primeiro argumento deve ser Boolean, mas os
     tipos do segundo e terceiro argumentos não precisão ser!
   •   either (b: Bool) (x1: τ) (x2: τ) =
            if b then x1 else x2

   • O tipo da função para Boolean → τ → τ → τ
   •   translate (x: Char) =
          either (isspace x) x '*'
   •   max (m: Int, n: Int) =
                                            Aplicação   legal   da       função
           either (m > n) m n'              either
                                                        7-19
Tipos parametrizados

 Um tipo parametrizado é um tipo que toma outros tipos
  como parâmetros
   • Pode-se imaginar o τ[] como um tipo parametrizado de C, que pode
     ser especializado num tipo ordinário, como char[], ou float[], ou
     float[][], pela substituição da variável τ por um tipo real
   • Todas as linguagens de programação têm tipos parametrizados pré-
     definidos
       – C, C++ e Java têm τ[]
       – Ada tem array (σ) of e access τ

   • Poucas linguagens de programação, como ML e Haskell permitem que
     o programador defina seus próprios tipos parametrizados
                                                   7-20
Exemplo: tipo parametrizado em Haskell

  Definição de um tipo de pares homogêneos
    •   type Pair τ =(τ, τ)

    •   τ   é um parâmetro do tipo e denota um tipo arbitrário

    • Uma especialização deste tipo poderia ser
            – Pair Int

            – com o tipo resultante Integer × Integer, ou seja valores pares de números
              inteiros

            – ou
            – Pair Float

            – com o tipo resultante Real × Real, ou seja valores pares de números reais
                                                                  7-21
Exemplo: tipo parametrizado recursivo em
                 Haskell
  Definição de listas homogêneas                   List<τ> = Unit + (τ × List<τ>)
    •   data List τ = Nil | Cons (τ, List τ)

    • Agora, List     Int   é um tipo cujos valores são listas de inteiros
    •   head (l: List τ)=                      head : List<τ> → τ
           case l of
             Nil -> ... -- error
             Cons(x,xs) -> x

        tail (l: List τ)=                      tail : List<τ> → List<τ>
           case l of
             Nil -> ... -- error
             Cons(x,xs) -> xs

        length (l: List τ)=              length:      List<τ> → Integer
            case l of
              Nil -> 0
              Cons(x,xs) -> 1 + length(xs)



                                                               7-22
Inferência de tipos

 A maioria das linguagens estaticamente tipadas requerem que
  o programador declare explicitamente os tipos usados em toda
  entidade declarada num programa
   •   I: constant T := E;
       I: T;
       function I (I': T') return T;


 Em Haskell, os tipos não precisam ser explicitados – são
  inferidos do contexto
 Inferência de tipos é um processo pelo qual o tipo de uma
  entidade declarada é inferido, quando não foi explicitamente
  estabelecido
                                               7-23
Exemplo: inferência de tipos monomórficos
               em Haskell
   Considere a seguinte definição de função
     •   even n = (n 'mod' 2 = 0)

     • Sabe-se que o operador mod tem tipo Integer × Integer → Integer

     • A partir da subexpressão n   'mod' 2   pode-se inferir que o tipo de n
         é Integer

     • De forma similar, pode-se inferir que o corpo da função tem o tipo
         Boolean

     • Logo, a função even tem o monotipo Integer → Boolean

     • Nem sempre pode inferir um monotipo!

                                                             7-24
Exemplo: inferência de tipos polimórficos em
                  Haskell
    Considere a seguinte função
      •   f . g =
               x -> f(g(x))

      • Nota-se que f e g são funções, que o tipo resultante de g deve ser o
        mesmo tipo do parâmetro de f, mas nada se pode inferir que tipo é
        este, ele é um politipo β qualquer
      • Nada se pode afirmar dos tipos do parâmetro de g e do valor
        resultante de f, que podem ser diferentes, eles podem ter os
        politipos α e γ, respectivamente
      • Neste caso, o tipo de x obrigatoriamente é α
      • Logo, o tipo da função acima é
           – (β → γ) → (α → β) → (α → γ)


                                                           7-25
Sobrecarga (1)

 Um identificador está sobrecarregado se ele denota dois

  ou mais procedimentos num mesmo escopo
   • Aceitável apenas quando a chamada do procedimento pode ser

     feita sem ambigüidade

 Pode ser definida pelo programador em Java, C++, Ada,

  dentre outras linguagens




                                                   7-26
Exemplo: funções sobrecarregadas em C

 O operador "–" em C denota simultaneamente quatro
  funções pré-definidas
   • Negação de inteiros (função com tipo Integer → Integer)

   • Negação de ponto-flutuante (função com tipo Float → Float)

   • Subtração de inteiro (função com tipo Integer × Integer → Integer)

   • Subtração de ponto-flutuante (função com tipo Float × Float → Float)

 Nota-se que não há ambigüidade, pois o número e os tipos
  dos operandos determinam a função a chamar


                                                         7-27
Exemplo: funções sobrecarregadas em Ada

  O operador "/" denota duas funções pré-definidas em Ada
    • Divisão de inteiros (função com tipo Integer × Integer → Integer)
    • Divisão de ponto-flutuante (função com tipo Float × Float → Float)
  Pode-se declarar a função sobrecarregada abaixo
    •   function "/" (m, n: Integer) return Float;
        -- Return the quotient of m and n as a real number.
    • cujo tipo é (função com tipo Integer × Integer → Float)
    • Neste caso, a função a chamar vai depender do contexto onde é
      aplicada e não apenas dos parâmetros reais
    •   n: Integer; x: Float;
        ...
    •   x   :=   7.0/2.0;       -   computes   7.0/2.0 = 3.5
        x   :=   7/2;           -   computes   7/2 = 3.5
        n   :=   7/2;           -   computes   7/2 = 3
        n   :=   (7/2)/(5/2);   -   computes   (7/2)/(5/2) = 3/2 = 1
    • Algumas chamadas são ambíguas e ilegais
            – x := (7/2)/(5/2); - computes (7/2)/(5/2) = 3/2 = 1.5      ou
                                                                    7-28
                                                (7/2)/(5/2) = 3.5/2.5 = 1.5
Sobrecarga (2)

 Suponha um identificador F denotando simultaneamente
  duas funções f1: S1 → T1 e f2: S2 → T2
   • Sobrecarga independente de contexto: requer que S1 e S2 sejam
     não equivalentes
       – A função a ser chamada sempre pode ser univocamente identificada
         pelo tipo do parâmetro real
   • Sobrecarga dependente de contexto: requer apenas que S1 e S2
     sejam não equivalentes ou que T1 e T2 sejam não equivalentes
       – Quando S1 e S2 são equivalentes, o contexto onde o F é utilizado deve
         ser levado em conta para identificar a função a ser chamada
       – Possibilita a formulação de expressões nas quais a função a ser
         chamada não pode ser determinada univocamente – tais construções
         ambíguas devem ser proibidas                   7-29
Sobrecarga (3)

 Advertência!
   • Não confundir sobrecarga – também conhecido como
     polimorfismo ad hoc – com polimorfismo paramétrico
      – A sobrecarga não aumenta o poder de expressividade da linguagem
        de programação, visto que a quantidade de funções sobrecarregadas
        sempre é limitada

      – Por outro lado, o polimorfismo paramétrico permite que um
        procedimento opere sobre um número potencialmente ilimitado de
        variedade de tipos



                                                         7-30
Conversão de tipos (1)

 Uma conversão de tipos é um mapeamento de valores de

  um tipo para valores correspondentes de outro tipo
   • Exemplos:

      – Mapeamento natural de números inteiros para reais

           {..., −2 → −2.0, −1 → −1.0, 0 → 0.0, +1 → +1.0, +2 → +2.0, ...}


      – Truncamento e o arredondamento são opções de conversão de tipos
        de real para inteiros

      – Mapeamento de caracteres para strings de tamanho 1


                                                                  7-31
Conversão de tipos (2)


 Conversões de tipos podem ser mapeamentos totais

   • Caracteres para códigos de caracteres, inteiros para reais, ...


 Conversões de tipos podem ser mapeamentos parciais

   • Códigos de caracteres para caracteres, reais para inteiros, ...

   • Mapeamentos parciais podem provocar falhas em programas



                                                          7-32
Conversão de tipos (3)

 Conversões de tipos podem ser explícitas ou implícitas
   • Um cast é uma conversão de tipos explícita
       – Em C, C++ e Java, um cast tem a forma (T)E
       – Em Ada e em Object Pascal, um cast tem a forma T(E)
            Caso a subexpressão E é do tipo S – não equivalente a T – e se a
             linguagem de programação define uma conversão de tipo de S para T,
             então o cast mapeia o valor de E para o valor correspondente de T

   • Uma coerção é uma conversão de tipos implícita, realizada
     automaticamente sempre que o contexto sintático exigir
       – Considere a expressão E no contexto do tipo T
            Se o tipo de E é S – não equivalente a T – e se a linguagem permite a
             coerção de S para T nesse contexto, então a coerção mapeia o valor de E
             para o valor correspondente de T
                                                               7-33
Exemplo: coerções e Pascal e casts em Ada

  Pascal
    •   var n: Integer; x : Real;
        ...
        x := n;            -- converte o valor de n para um número real
        n := x;            -- ilegal!
        n := round(x)      -- converte o valor de x para um inteiro por arredondamento

  Ada
    • Ada não prover nenhum tipo de coerção
    •   n: Integer; x : Float;
        ...
        x := n;            -- ilegal!
        n := x;            -- ilegal!
        x := Float(n)      -- converte o valor de n para um número real
        n := Integer(x)    -- converte o valor de x para um inteiro por arredondamento

  Algumas linguagens de programação são muitos permissivas
   em relação às coerções, e. g. C, Java
  A tendência é reduzir ou mesmo eliminar coerções nas
   linguagens de programação mais modernas 7-34
Notas de Implementação (1)

 Implementação do polimorfismo paramétrico
   • Procedimento polimórficos operam uniformemente sobre argumento de
     uma família de tipos
   • Opções de implementação
       – Gera uma instância separada de procedimento para cada tipo distinto de
         argumento
            Inviável na prática!

       – Representar os valores de todos os tipos de tal modo que eles pareçam
         similar para o procedimento polimórfico
            Representar cada valor através de um apontador para o objeto na memória
             heap


                                                            7-35
Notas de Implementação (2)

 Considere as funções polimórficas
   • Estas funções somente copia valores do tipo τ e isto é implementado
     copiando-se os ponteiros para estes valores
       – either: Boolean → τ → τ → τ

       – second: σ × τ → τ

       – head : List<τ> → τ

   • Esta implementação de funções paramétricas é simples e uniforme, porém de
     alto custo
       – Todos os valores – incluindo valores primitivos – devem ser armazenados na
         memória heap e acessados através de apontadores
       – Espaço na memória deve ser alocado quando eles são usados da primeira vez e
         desalocado pelo gerenciador de memória quando não são mais necessários
                                                            7-36

Mais conteúdo relacionado

Mais procurados

02. tipos de_dados,_constantes_e_variáveis
02. tipos de_dados,_constantes_e_variáveis02. tipos de_dados,_constantes_e_variáveis
02. tipos de_dados,_constantes_e_variáveisGilson Bezerra
 
Fundamentos do .NET Framework - Parte 2
Fundamentos do .NET Framework - Parte 2Fundamentos do .NET Framework - Parte 2
Fundamentos do .NET Framework - Parte 2Julian Correa
 
Ponteiros e Alocação Dinâmica
Ponteiros e Alocação DinâmicaPonteiros e Alocação Dinâmica
Ponteiros e Alocação DinâmicaEduardo Oliveira
 
Estrutura de dados em Java - Ponteiros e Alocação de Memória
Estrutura de dados em Java - Ponteiros e Alocação de Memória Estrutura de dados em Java - Ponteiros e Alocação de Memória
Estrutura de dados em Java - Ponteiros e Alocação de Memória Adriano Teixeira de Souza
 
Haskell aula2 tipos-e-classes
Haskell aula2 tipos-e-classesHaskell aula2 tipos-e-classes
Haskell aula2 tipos-e-classesCRISLANIO MACEDO
 
Aula 06 vetores e matrizes
Aula 06   vetores e matrizesAula 06   vetores e matrizes
Aula 06 vetores e matrizesTácito Graça
 
Java 03 Tipos Dados Operadores
Java 03 Tipos Dados OperadoresJava 03 Tipos Dados Operadores
Java 03 Tipos Dados OperadoresRegis Magalhães
 
09 programando em python - classes
 09   programando em python - classes 09   programando em python - classes
09 programando em python - classesVictor Marcelino
 
Estrutura de Dados - Alocação dinâmica de memória
Estrutura de Dados - Alocação dinâmica de memóriaEstrutura de Dados - Alocação dinâmica de memória
Estrutura de Dados - Alocação dinâmica de memóriaAdriano Teixeira de Souza
 
Scala: unindo programação funcional e orientação a objetos
Scala: unindo programação funcional e orientação a objetosScala: unindo programação funcional e orientação a objetos
Scala: unindo programação funcional e orientação a objetosFelipe Hummel
 
Orientação a Objetos em Python
Orientação a Objetos em PythonOrientação a Objetos em Python
Orientação a Objetos em PythonLuciano Ramalho
 
Algoritmos e lp parte 2-fundamentos
Algoritmos e lp parte 2-fundamentosAlgoritmos e lp parte 2-fundamentos
Algoritmos e lp parte 2-fundamentosMauro Pereira
 
Programando em python classes
Programando em python   classesProgramando em python   classes
Programando em python classessamuelthiago
 
1º introdução a lógica de programação
1º   introdução a lógica de programação1º   introdução a lógica de programação
1º introdução a lógica de programaçãoLucas Mendes
 

Mais procurados (20)

Fundamentos do java
Fundamentos do javaFundamentos do java
Fundamentos do java
 
02. tipos de_dados,_constantes_e_variáveis
02. tipos de_dados,_constantes_e_variáveis02. tipos de_dados,_constantes_e_variáveis
02. tipos de_dados,_constantes_e_variáveis
 
Aula02
Aula02Aula02
Aula02
 
Standard ML / CPN ML
Standard ML / CPN MLStandard ML / CPN ML
Standard ML / CPN ML
 
Java 05
Java 05Java 05
Java 05
 
Fundamentos do .NET Framework - Parte 2
Fundamentos do .NET Framework - Parte 2Fundamentos do .NET Framework - Parte 2
Fundamentos do .NET Framework - Parte 2
 
Ponteiros e Alocação Dinâmica
Ponteiros e Alocação DinâmicaPonteiros e Alocação Dinâmica
Ponteiros e Alocação Dinâmica
 
Apostila de Alocação Dinâmica em C
Apostila de Alocação Dinâmica em CApostila de Alocação Dinâmica em C
Apostila de Alocação Dinâmica em C
 
Estrutura de dados em Java - Ponteiros e Alocação de Memória
Estrutura de dados em Java - Ponteiros e Alocação de Memória Estrutura de dados em Java - Ponteiros e Alocação de Memória
Estrutura de dados em Java - Ponteiros e Alocação de Memória
 
Haskell aula2 tipos-e-classes
Haskell aula2 tipos-e-classesHaskell aula2 tipos-e-classes
Haskell aula2 tipos-e-classes
 
Aula 06 vetores e matrizes
Aula 06   vetores e matrizesAula 06   vetores e matrizes
Aula 06 vetores e matrizes
 
Ed1
Ed1Ed1
Ed1
 
Java 03 Tipos Dados Operadores
Java 03 Tipos Dados OperadoresJava 03 Tipos Dados Operadores
Java 03 Tipos Dados Operadores
 
09 programando em python - classes
 09   programando em python - classes 09   programando em python - classes
09 programando em python - classes
 
Estrutura de Dados - Alocação dinâmica de memória
Estrutura de Dados - Alocação dinâmica de memóriaEstrutura de Dados - Alocação dinâmica de memória
Estrutura de Dados - Alocação dinâmica de memória
 
Scala: unindo programação funcional e orientação a objetos
Scala: unindo programação funcional e orientação a objetosScala: unindo programação funcional e orientação a objetos
Scala: unindo programação funcional e orientação a objetos
 
Orientação a Objetos em Python
Orientação a Objetos em PythonOrientação a Objetos em Python
Orientação a Objetos em Python
 
Algoritmos e lp parte 2-fundamentos
Algoritmos e lp parte 2-fundamentosAlgoritmos e lp parte 2-fundamentos
Algoritmos e lp parte 2-fundamentos
 
Programando em python classes
Programando em python   classesProgramando em python   classes
Programando em python classes
 
1º introdução a lógica de programação
1º   introdução a lógica de programação1º   introdução a lógica de programação
1º introdução a lógica de programação
 

Semelhante a Sistemas de Tipos Polimórficos

Paradigma Funcional - Caso de Estudo Haskell
Paradigma Funcional - Caso de Estudo HaskellParadigma Funcional - Caso de Estudo Haskell
Paradigma Funcional - Caso de Estudo HaskellSérgio Souza Costa
 
.200.2023-01.Categorias em Bancos de Dados.PT.pdf
.200.2023-01.Categorias em Bancos de Dados.PT.pdf.200.2023-01.Categorias em Bancos de Dados.PT.pdf
.200.2023-01.Categorias em Bancos de Dados.PT.pdfBrunoBraga94
 
Paradigmas de Linguagens de Programação - Tipos primitivos e compostos
Paradigmas de Linguagens de Programação - Tipos primitivos e compostosParadigmas de Linguagens de Programação - Tipos primitivos e compostos
Paradigmas de Linguagens de Programação - Tipos primitivos e compostosAdriano Teixeira de Souza
 
3 modelo relacional
3 modelo relacional3 modelo relacional
3 modelo relacionalMarcos Souza
 
Aula3-POO-ConceitosBasicos.pdf
Aula3-POO-ConceitosBasicos.pdfAula3-POO-ConceitosBasicos.pdf
Aula3-POO-ConceitosBasicos.pdfssuser6e99cd
 
Introdução a Python - Python Poli
Introdução a Python  - Python PoliIntrodução a Python  - Python Poli
Introdução a Python - Python PoliRodrigo Lira
 
Aula2 ambientação a linguagem deprogramação python
Aula2   ambientação a linguagem deprogramação pythonAula2   ambientação a linguagem deprogramação python
Aula2 ambientação a linguagem deprogramação pythonCleyton Fábio
 
Estrutura de dados
Estrutura de dadosEstrutura de dados
Estrutura de dadosgjpbg
 
Apostila estrutura de dados 2
Apostila estrutura de dados 2Apostila estrutura de dados 2
Apostila estrutura de dados 2Leandro Lopes
 
Introdução a Linguagem de Programação Ruby
Introdução a Linguagem de Programação RubyIntrodução a Linguagem de Programação Ruby
Introdução a Linguagem de Programação RubyDiego Rubin
 

Semelhante a Sistemas de Tipos Polimórficos (20)

tipos.ppt
tipos.ppttipos.ppt
tipos.ppt
 
Paradigma Funcional - Caso de Estudo Haskell
Paradigma Funcional - Caso de Estudo HaskellParadigma Funcional - Caso de Estudo Haskell
Paradigma Funcional - Caso de Estudo Haskell
 
.200.2023-01.Categorias em Bancos de Dados.PT.pdf
.200.2023-01.Categorias em Bancos de Dados.PT.pdf.200.2023-01.Categorias em Bancos de Dados.PT.pdf
.200.2023-01.Categorias em Bancos de Dados.PT.pdf
 
Introdução a Python
Introdução a PythonIntrodução a Python
Introdução a Python
 
Paradigmas de Linguagens de Programação - Tipos primitivos e compostos
Paradigmas de Linguagens de Programação - Tipos primitivos e compostosParadigmas de Linguagens de Programação - Tipos primitivos e compostos
Paradigmas de Linguagens de Programação - Tipos primitivos e compostos
 
Oz
OzOz
Oz
 
3 modelo relacional
3 modelo relacional3 modelo relacional
3 modelo relacional
 
Slide_Python.pdf
Slide_Python.pdfSlide_Python.pdf
Slide_Python.pdf
 
Aula3-POO-ConceitosBasicos.pdf
Aula3-POO-ConceitosBasicos.pdfAula3-POO-ConceitosBasicos.pdf
Aula3-POO-ConceitosBasicos.pdf
 
Unidade04
Unidade04Unidade04
Unidade04
 
Unidade7 1
Unidade7 1Unidade7 1
Unidade7 1
 
Introdução a Python - Python Poli
Introdução a Python  - Python PoliIntrodução a Python  - Python Poli
Introdução a Python - Python Poli
 
Aula2 ambientação a linguagem deprogramação python
Aula2   ambientação a linguagem deprogramação pythonAula2   ambientação a linguagem deprogramação python
Aula2 ambientação a linguagem deprogramação python
 
Estrutura de dados
Estrutura de dadosEstrutura de dados
Estrutura de dados
 
Apostila estrutura de dados 2
Apostila estrutura de dados 2Apostila estrutura de dados 2
Apostila estrutura de dados 2
 
Introdução ao paradigma funcional com scala
Introdução ao paradigma funcional com scalaIntrodução ao paradigma funcional com scala
Introdução ao paradigma funcional com scala
 
Fj pratica04
Fj pratica04Fj pratica04
Fj pratica04
 
Introdução a Linguagem de Programação Ruby
Introdução a Linguagem de Programação RubyIntrodução a Linguagem de Programação Ruby
Introdução a Linguagem de Programação Ruby
 
Linguagem lua
Linguagem luaLinguagem lua
Linguagem lua
 
Java2
Java2Java2
Java2
 

Sistemas de Tipos Polimórficos

  • 1. 8 Sistemas de Tipos  Polimorfismo de inclusão.  Polimorfismo paramétrico.  Sobrecarga.  Conversões de tipos.  Notas de implementação. 7-1
  • 2. Polimorfismo de inclusão (1)  Polimorfismo de inclusão é um sistema de tipo no qual um tipo pode ter subtipos, que herdam as operações daquele tipo • Conceito-chave das linguagem orientadas a objetos  Tipos e subtipos • Um tipo T é um conjunto de valores equipado com operações • Um subtipo de T é um subconjunto dos valores de T equipado com as mesmas operações de T – Todo valor do subtipo também é valor do tipo T, podendo ser usado no contexto onde um valor do tipo T é esperado – O conceito de subtipos é uma idéia útil e comum em programação 7-2
  • 3. Exemplo: tipos primitivos e subtipos em Ada  Declarações em Ada definindo subtipos de Integer • subtype Natural is Integer range 0 .. Integer'last; subtype Small is Integer range -3 .. +3; • Conjuntos de valores correspondentes – Natural = {0, 1, 2, 3, 4, 5, 6, ...} Small = {-3, -2, -1, 0, +1, +2, +3} • Variáveis i := n; Requer verificação em – i: Integer; i := s; tempo de execução n: Natural; s: Small; n := i; n := s; s := i; s := n: 7-3
  • 4. Exemplo: tipos e subtipo de registros discriminados em Ada (1)  Declaração de registro discriminado em Ada • type Form is (pointy, circular, rectangular); type Figure (f: Form := pointy) is record x, y: Float; case f is when pointy => null; when circular => r: Float; when rectangular => h, w: Float; end case; end record; subtype Point is Figure(pointy); subtype Circle is Figure(circular); subtype Rectangle is Figure(rectangular); • Conjuntos de valores – Form = {pointy, circular, rectangular} Figure = pointy(Float × Float) + circular(Float × Float × Float) + rectangular(Float × Float × Float × Float) 7-4
  • 5. Exemplo: tipos e subtipo de registros discriminados em Ada (2)  Conjunto de valores dos subtipos – Point = pointy(Float × Float) Circle = circular(Float × Float × Float) Rectangle = rectangular(Float × Float × Float × Float)  Exemplos de variáveis • diagram: array (...) of Figure; frame: Rectangle; cursor: Point; 7-5
  • 6. Polimorfismo de inclusão (2)  Em linguagens de programação que suportam subtipos, não é possível estabelecer univocamente o subtipo de um valor  Propriedades gerais dos subtipos • Condição necessária para S ser um subtipo de T: S ⊆ T • O tipo T é equipado com operações que são aplicáveis a todos os valores do tipo T • Todas essas operações também serão aplicáveis aos valores do subtipo S – S herda as perações de T 7-6
  • 7. Polimorfismo de inclusão (3)  Compatibilidade de tipos na presença de subtipos • V := E tipo = T2 tipo = T1 • T1 é compatível com T2 se e somente se T1 e T2 têm valores em comum – Ou T1 é um subtipo de T2 ou T2 é um subtipo de T1 ou T1 e T2 são subtipos de outro tipo qualquer • Casos de interesse quando T1 e T2 são compatíveis – T1 é um subtipo de T2: T1 pode ser usado com segurança num contexto onde um valor de T2 é esperado – não precisa de verificação em tempo de execução – T1 não é um subtipo de T2: valores do tipo T1 somente podem ser usados após verificação em tempo de execução para determinar se ele também é um valor do tipo T2 7-7
  • 8. Classes e subclasses  Uma classe C é um conjunto de objetos equipados com operações • Cada objeto da classe C tem uma ou mais variáveis componentes e está equipada com métodos que acessam essas variáveis • Cada objeto de uma subclasse S de C herda todas as variáveis componentes dos objetos da classe C, podendo ter variáveis componentes adicionais • Cada objeto da classe S potencialmente herda todos os métodos dos objetos da classe C e pode ser equipada com métodos adicionais para acessar tais variáveis • Qualquer objeto de uma subclasse pode ser usado no contexto onde um objeto da classe C é esperado  Subclasses não são o mesmo que subtipos em geral 7-8
  • 9. Exemplo: subclasses de Java como subtipos (1)  Considere as classes • class Point { protected double x, y; public void draw () {...} } class Circle extends Point { private double r; public void draw () {...} } class Rectangle extends Point { private double w, h; public void draw () {...} } 7-9
  • 10. Exemplo: subclasses de Java como subtipos (2)  Conjuntos de valores das classes – Point = Point(Double × Double) Circle = Circle(Double × Double × Double) Rectangle = Rectangle(Double × Double × Double × Double) • Nota-se que Circle e Rectangle não são subtipos de Point • Mas são subtipos do tipo Point$ abaixo – Point$ = Point(Double × Double) + Circle(Double × Double × Double) + Rectangle(Double × Double × Double × Double) Point$ 7-10
  • 11. Exemplo: subclasses de Java como subtipos (3)  Java permite que objetos de qualquer subclasse sejam tratados como objetos da superclasse • Point p; ... p= new Point(3.0, 4.0); ... p= new Circle(3.0, 4.0, 5.0); – Variáveis do classe Point podem referenciar quaisquer valores do tipo Point$ • Em geral, se C é uma classe, então C$ inclui não apenas os objetos da classe C, mas também os objetos de todas as subclasses de C – C$ é denominada de tipo de classe estendido (class-wide type) 7-11
  • 12. Exemplo: extensibilidade em Java (1)  Sejam as declarações considerando o exemplo anterior • class Line extends Point { private double length, orientation; public void draw () { ... } } class Textbox extends Rectangle { private String text; public void draw () { ... } } • As definições acima não apenas definem os conjuntos de objetos das novas classes – Line = Line(Double × Double × Double) Textbox = Textbox(Double × Double × String) 7-12
  • 13. Exemplo: extensibilidade em Java (2) • como também definem os tipos de classe estendidos abaixo – Point$ = Point(Double × Double) + Circle(Double × Double × Double) + Rectangle(Double × Double × Double × Double) + Line(Double × Double × Double) + Textbox(Double × Double × String) – Rectangle$ = Rectangle(Double × Double × Double × Double) + Textbox(Double × Double × String) 7-13
  • 14. Polimorfismo paramétrico (1)  Polimorfismo paramétrico é um sistema de tipos que permite que se escrevam procedimentos polimórficos • Um procedimento polimórfico é aquele que pode operar uniformemente sobre argumentos de toda uma família de tipos • Um procedimento monomórfico é aquele que somente pode operar sobre argumentos de um tipo fixo – Uma função que computar o tamanho de uma lista de caracteres não pode ser aplicada a listas de inteiros, por exemplo 7-14
  • 15. Polimorfismo paramétrico (2)  Procedimentos polimórficos • Suportado naturalmente em Haskell – Basta que se declare o tipo da função utilizando variáveis de tipo, em vez de tipos específicos  Uma variável de tipo é um identificador que denota um tipo de uma família de tipos » Letras romanas minúsculas em Haskell » Letras gregas nos exemplos do livro-texto (α, β, γ, ...) 7-15
  • 16. Exemplo: função polimórfica em Haskell (1)  Função monomórfica em Haskell • second (x: Int, y: Int) = y • Tipo da função – Integer × Integer → Integer – second(13, 21) resulta no valor 21, mas a chamada second(13, true) é ilegal, pois os tipos não casam  A versão polimórfica desta função resolve este problema • second (x: σ, y: τ) = y • Tipo da função – σ×τ→τ – σ e τ são variáveis de tipo, cada uma representação de um tipo arbitrário 7-16
  • 17. Exemplo: função polimórfica em Haskell (2) • Agora, a chamada da função abaixo é legal – second(13, true) resulta no valor true – O tipo da função determinado pelo casamento de tipos é o seguinte  σ  Integer e τ  Boolean  Substituíndo ambos no tipo σ × τ → τ, tem-se o tipo resultante da aplicação da função  Integer × Boolean → Boolean  Esta função polimórfica aceitas argumentos de muitos tipos, mas não quaisquer argumentos • Apenas pares da forma σ × τ • As chamadas abaixo são ilegais – second(13) – second(1978, 5, 5) 7-17
  • 18. Polimorfismo paramétrico (3)  Um politipo deriva uma família de tipos e sempre possui uma ou mais variáveis de tipo ∀ σ × τ e σ × τ → τ são exemplos de politipos • Politipos derivam uma família de tipos pela substituição sistemática das variáveis de tipo por tipos – A família de tipos derivada por σ × τ → τ, incluem  Integer × Boolean → Boolean  String × String → String – mas não incluem  Integer × Boolean → Integer  Integer → Integer  String × String × String → String 7-18
  • 19. Exemplo: função polimórfica em Haskell  Considere a seguinte função monomórfica em Haskell • either (b: Bool) (x1: Char) (x2: Char) = if b then x1 else x2 • O tipo dessa função é Boolean → Character → Character → Character • translate (x: Char) = either (isspace x) x '*' • Nota-se que o tipo do primeiro argumento deve ser Boolean, mas os tipos do segundo e terceiro argumentos não precisão ser! • either (b: Bool) (x1: τ) (x2: τ) = if b then x1 else x2 • O tipo da função para Boolean → τ → τ → τ • translate (x: Char) = either (isspace x) x '*' • max (m: Int, n: Int) = Aplicação legal da função either (m > n) m n' either 7-19
  • 20. Tipos parametrizados  Um tipo parametrizado é um tipo que toma outros tipos como parâmetros • Pode-se imaginar o τ[] como um tipo parametrizado de C, que pode ser especializado num tipo ordinário, como char[], ou float[], ou float[][], pela substituição da variável τ por um tipo real • Todas as linguagens de programação têm tipos parametrizados pré- definidos – C, C++ e Java têm τ[] – Ada tem array (σ) of e access τ • Poucas linguagens de programação, como ML e Haskell permitem que o programador defina seus próprios tipos parametrizados 7-20
  • 21. Exemplo: tipo parametrizado em Haskell  Definição de um tipo de pares homogêneos • type Pair τ =(τ, τ) • τ é um parâmetro do tipo e denota um tipo arbitrário • Uma especialização deste tipo poderia ser – Pair Int – com o tipo resultante Integer × Integer, ou seja valores pares de números inteiros – ou – Pair Float – com o tipo resultante Real × Real, ou seja valores pares de números reais 7-21
  • 22. Exemplo: tipo parametrizado recursivo em Haskell  Definição de listas homogêneas List<τ> = Unit + (τ × List<τ>) • data List τ = Nil | Cons (τ, List τ) • Agora, List Int é um tipo cujos valores são listas de inteiros • head (l: List τ)= head : List<τ> → τ case l of Nil -> ... -- error Cons(x,xs) -> x tail (l: List τ)= tail : List<τ> → List<τ> case l of Nil -> ... -- error Cons(x,xs) -> xs length (l: List τ)= length: List<τ> → Integer case l of Nil -> 0 Cons(x,xs) -> 1 + length(xs) 7-22
  • 23. Inferência de tipos  A maioria das linguagens estaticamente tipadas requerem que o programador declare explicitamente os tipos usados em toda entidade declarada num programa • I: constant T := E; I: T; function I (I': T') return T;  Em Haskell, os tipos não precisam ser explicitados – são inferidos do contexto  Inferência de tipos é um processo pelo qual o tipo de uma entidade declarada é inferido, quando não foi explicitamente estabelecido 7-23
  • 24. Exemplo: inferência de tipos monomórficos em Haskell  Considere a seguinte definição de função • even n = (n 'mod' 2 = 0) • Sabe-se que o operador mod tem tipo Integer × Integer → Integer • A partir da subexpressão n 'mod' 2 pode-se inferir que o tipo de n é Integer • De forma similar, pode-se inferir que o corpo da função tem o tipo Boolean • Logo, a função even tem o monotipo Integer → Boolean • Nem sempre pode inferir um monotipo! 7-24
  • 25. Exemplo: inferência de tipos polimórficos em Haskell  Considere a seguinte função • f . g = x -> f(g(x)) • Nota-se que f e g são funções, que o tipo resultante de g deve ser o mesmo tipo do parâmetro de f, mas nada se pode inferir que tipo é este, ele é um politipo β qualquer • Nada se pode afirmar dos tipos do parâmetro de g e do valor resultante de f, que podem ser diferentes, eles podem ter os politipos α e γ, respectivamente • Neste caso, o tipo de x obrigatoriamente é α • Logo, o tipo da função acima é – (β → γ) → (α → β) → (α → γ) 7-25
  • 26. Sobrecarga (1)  Um identificador está sobrecarregado se ele denota dois ou mais procedimentos num mesmo escopo • Aceitável apenas quando a chamada do procedimento pode ser feita sem ambigüidade  Pode ser definida pelo programador em Java, C++, Ada, dentre outras linguagens 7-26
  • 27. Exemplo: funções sobrecarregadas em C  O operador "–" em C denota simultaneamente quatro funções pré-definidas • Negação de inteiros (função com tipo Integer → Integer) • Negação de ponto-flutuante (função com tipo Float → Float) • Subtração de inteiro (função com tipo Integer × Integer → Integer) • Subtração de ponto-flutuante (função com tipo Float × Float → Float)  Nota-se que não há ambigüidade, pois o número e os tipos dos operandos determinam a função a chamar 7-27
  • 28. Exemplo: funções sobrecarregadas em Ada  O operador "/" denota duas funções pré-definidas em Ada • Divisão de inteiros (função com tipo Integer × Integer → Integer) • Divisão de ponto-flutuante (função com tipo Float × Float → Float)  Pode-se declarar a função sobrecarregada abaixo • function "/" (m, n: Integer) return Float; -- Return the quotient of m and n as a real number. • cujo tipo é (função com tipo Integer × Integer → Float) • Neste caso, a função a chamar vai depender do contexto onde é aplicada e não apenas dos parâmetros reais • n: Integer; x: Float; ... • x := 7.0/2.0; - computes 7.0/2.0 = 3.5 x := 7/2; - computes 7/2 = 3.5 n := 7/2; - computes 7/2 = 3 n := (7/2)/(5/2); - computes (7/2)/(5/2) = 3/2 = 1 • Algumas chamadas são ambíguas e ilegais – x := (7/2)/(5/2); - computes (7/2)/(5/2) = 3/2 = 1.5 ou 7-28 (7/2)/(5/2) = 3.5/2.5 = 1.5
  • 29. Sobrecarga (2)  Suponha um identificador F denotando simultaneamente duas funções f1: S1 → T1 e f2: S2 → T2 • Sobrecarga independente de contexto: requer que S1 e S2 sejam não equivalentes – A função a ser chamada sempre pode ser univocamente identificada pelo tipo do parâmetro real • Sobrecarga dependente de contexto: requer apenas que S1 e S2 sejam não equivalentes ou que T1 e T2 sejam não equivalentes – Quando S1 e S2 são equivalentes, o contexto onde o F é utilizado deve ser levado em conta para identificar a função a ser chamada – Possibilita a formulação de expressões nas quais a função a ser chamada não pode ser determinada univocamente – tais construções ambíguas devem ser proibidas 7-29
  • 30. Sobrecarga (3)  Advertência! • Não confundir sobrecarga – também conhecido como polimorfismo ad hoc – com polimorfismo paramétrico – A sobrecarga não aumenta o poder de expressividade da linguagem de programação, visto que a quantidade de funções sobrecarregadas sempre é limitada – Por outro lado, o polimorfismo paramétrico permite que um procedimento opere sobre um número potencialmente ilimitado de variedade de tipos 7-30
  • 31. Conversão de tipos (1)  Uma conversão de tipos é um mapeamento de valores de um tipo para valores correspondentes de outro tipo • Exemplos: – Mapeamento natural de números inteiros para reais  {..., −2 → −2.0, −1 → −1.0, 0 → 0.0, +1 → +1.0, +2 → +2.0, ...} – Truncamento e o arredondamento são opções de conversão de tipos de real para inteiros – Mapeamento de caracteres para strings de tamanho 1 7-31
  • 32. Conversão de tipos (2)  Conversões de tipos podem ser mapeamentos totais • Caracteres para códigos de caracteres, inteiros para reais, ...  Conversões de tipos podem ser mapeamentos parciais • Códigos de caracteres para caracteres, reais para inteiros, ... • Mapeamentos parciais podem provocar falhas em programas 7-32
  • 33. Conversão de tipos (3)  Conversões de tipos podem ser explícitas ou implícitas • Um cast é uma conversão de tipos explícita – Em C, C++ e Java, um cast tem a forma (T)E – Em Ada e em Object Pascal, um cast tem a forma T(E)  Caso a subexpressão E é do tipo S – não equivalente a T – e se a linguagem de programação define uma conversão de tipo de S para T, então o cast mapeia o valor de E para o valor correspondente de T • Uma coerção é uma conversão de tipos implícita, realizada automaticamente sempre que o contexto sintático exigir – Considere a expressão E no contexto do tipo T  Se o tipo de E é S – não equivalente a T – e se a linguagem permite a coerção de S para T nesse contexto, então a coerção mapeia o valor de E para o valor correspondente de T 7-33
  • 34. Exemplo: coerções e Pascal e casts em Ada  Pascal • var n: Integer; x : Real; ... x := n; -- converte o valor de n para um número real n := x; -- ilegal! n := round(x) -- converte o valor de x para um inteiro por arredondamento  Ada • Ada não prover nenhum tipo de coerção • n: Integer; x : Float; ... x := n; -- ilegal! n := x; -- ilegal! x := Float(n) -- converte o valor de n para um número real n := Integer(x) -- converte o valor de x para um inteiro por arredondamento  Algumas linguagens de programação são muitos permissivas em relação às coerções, e. g. C, Java  A tendência é reduzir ou mesmo eliminar coerções nas linguagens de programação mais modernas 7-34
  • 35. Notas de Implementação (1)  Implementação do polimorfismo paramétrico • Procedimento polimórficos operam uniformemente sobre argumento de uma família de tipos • Opções de implementação – Gera uma instância separada de procedimento para cada tipo distinto de argumento  Inviável na prática! – Representar os valores de todos os tipos de tal modo que eles pareçam similar para o procedimento polimórfico  Representar cada valor através de um apontador para o objeto na memória heap 7-35
  • 36. Notas de Implementação (2)  Considere as funções polimórficas • Estas funções somente copia valores do tipo τ e isto é implementado copiando-se os ponteiros para estes valores – either: Boolean → τ → τ → τ – second: σ × τ → τ – head : List<τ> → τ • Esta implementação de funções paramétricas é simples e uniforme, porém de alto custo – Todos os valores – incluindo valores primitivos – devem ser armazenados na memória heap e acessados através de apontadores – Espaço na memória deve ser alocado quando eles são usados da primeira vez e desalocado pelo gerenciador de memória quando não são mais necessários 7-36