Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

João Batista Neto

[Resolvido] Arrays com tipo definido

Recommended Posts

Talvez a maior vantagem do PHP que é a flexibilidade seja também sua maior desvantagem.

 

Algumas vezes, durante o desenvolvimento de uma aplicação, precisamos utilizar listas (matrizes) com um tipo de dado específico, porém como garantir que uma matriz de inteiros tenha somente inteiros ou uma matriz de string não tenha nada que não seja uma string ??

 

Para conseguir "tipar" uma matriz é possível especializar a classe ArrayObject e fazer a validação em tempo de execução:

 

    class ArrayOfInteger extends ArrayObject {
        /**
         * Constroi uma nova matriz de inteiros
         */
        public function __construct(){
            $argv = func_get_args();
    
            foreach ( $argv as $arg ){
                if ( ( gettype( $arg ) == "array" ) || ( $arg instanceOf ArrayOfInteger ) ){
                    foreach ( $arg as $key => $value ){
                        $this->offsetSet( $key , $value );
                    }
                } else {
                    $this->append( $arg );
                }
            }
        }
    
        /**
         * Faz a validação do tipo
         * @param mixed $value O valor que será validado
         * @return boolean
         */
        private function validate( $value ){
            $ret = false;
    
            if ( ( $type = gettype( $value ) ) == "integer" ){
                $ret = true;
            } else {
                throw new UnexpectedValueException( sprintf( "ArrayOfInteger aceita apenas inteiros, %s foi dado." , $type ) );
            }
    
            return( $ret );
        }
    
        /**
         * Adicionando a validação ao método offsetSet
         * @see ArrayObject::offsetSet( $offset , $value )
         */
        public function offsetSet( $offset , $value ){
            if ( $this->validate( $value ) ){
                parent::offsetSet( $offset , $value );
            }
        }
    
        /**
         * Adicionando a validação ao método append
         * @see ArrayObject::append( $value )
         */
        public function append( $value ){
            if ( $this->validate( $value ) ){
                parent::append( $value );
            }
        }
    }

Com a classe acima podemos criar uma matriz de inteiros que só aceita inteiros:

 

    $ints = new ArrayOfInteger( 1 , 2 , 3 );
    $ints[] = 10;
    $ints[] = 20;
    $ints[] = 30;
    $ints[] = '30'; //Isso causará um erro pois nossa matriz aceita apenas inteiros

A classe acima aceita apenas inteiros, porém durante o desenvolvimento de uma aplicação podemos precisar de matrizes de inteiros, strings, doubles, booleans.....

Para isso podemos criar uma classe base e criar as classes tipadas para cada tipo específico:

 

 /**
  * Classe base para a definição de uma lista tipada
  *
  * @abstract
  * @author João Batista Neto <neto.joaobatista@gmail.com>
  * @category Types
  */
 abstract class ArrayOf extends ArrayObject {
     /**
      * Constroi uma nova matriz tipada
      */
     final public function __construct(){
         $argv = func_get_args();
 
         foreach ( $argv as $arg ){
             if ( ( gettype( $arg ) == "array" ) || ( $arg instanceOf ArrayObject ) ){
                 foreach ( $arg as $key => $value ){
                     $this->offsetSet( $key , $value );
                 }
             } else {
                 $this->append( $arg );
             }
         }
     }
 
     /**
      * Adicionando a validação ao método append
      * @see ArrayObject::append( $value )
      */
     final public function append( $value ){
         if ( $this->pos_validate( $value ) ){
             parent::append( $value );
         }
     }
 
     /**
      * Adicionando a validação ao método offsetSet
      * @see ArrayObject::offsetSet( $offset , $value )
      */
     final public function offsetSet( $offset , $value ){
         if ( $this->pos_validate( $value ) ){
             parent::offsetSet( $offset , $value );
         }
     }
 
     /**
      * Faz a pós validação do tipo, validamos o retorno do método ArrayOf::validate para ver se é um boolean
      * @param mixed $value O valor que será validado
      * @return boolean
      */
     private function pos_validate( $value ){
         $ret = false;
         $validate = $this->validate( $value );
 
         if ( ( $type = gettype( $validate ) ) == "boolean" ){
             if ( $validate ){
                 $ret = true;
             } else {
                 throw new UnexpectedValueException( sprintf( "A lista %s não aceita valores do tipo %s." , get_class( $this ) , gettype( $value ) ) );
             }
         } else {
             throw new UnexpectedValueException( sprintf( "O método ArrayOf::validate( $value ) deve retornar um boolean, %s foi retornado." , $type ) );
         }
 
         return( $ret );
     }
 
     /**
      * Método que deverá ser implementado pelas classes especializadas
      * @abstract
      * @param mixed $value O valor que será validado
      * @return boolean
      */
     abstract protected function validate( $value );
 }

Com a classe acima podemos criar qualquer matriz tipada implementando apenas o método validate:

 

Matriz de Strings

    class ArrayOfStrings extends ArrayOf {
        /**
         * Faz a validação do tipo
         * @param mixed $value O valor que será validado
         * @return boolean
         */
        final protected function validate( $value ){
            $ret = false;
    
            if ( ( $type = gettype( $value ) ) == "string" ){
                $ret = true;
            } else {
                throw new UnexpectedValueException( sprintf( "ArrayOfStrings aceita apenas strings, %s foi dado." , $type ) );
            }
    
            return( $ret );
        }
    }

Matriz de Inteiros

    class ArrayOfIntegers extends ArrayOf {
        /**
         * Faz a validação do tipo
         * @param mixed $value O valor que será validado
         * @return boolean
         */
        final protected function validate( $value ){
            $ret = false;
    
            if ( ( $type = gettype( $value ) ) == "integer" ){
                $ret = true;
            } else {
                throw new UnexpectedValueException( sprintf( "ArrayOfIntegers aceita apenas inteiros, %s foi dado." , $type ) );
            }
    
            return( $ret );
        }
    }

Matriz de Doubles (números em ponto flutuante)

    class ArrayOfDoubles extends ArrayOf {
        /**
         * Faz a validação do tipo
         * @param mixed $value O valor que será validado
         * @return boolean
         */
        final protected function validate( $value ){
            $ret = false;
    
            if ( ( $type = gettype( $value ) ) == "double" ){
                $ret = true;
            } else {
                throw new UnexpectedValueException( sprintf( "ArrayOfDoubles aceita apenas números em ponto flutuante, %s foi dado." , $type ) );
            }
    
            return( $ret );
        }
    }

 

Matriz de Booleans

    class ArrayOfBooleans extends ArrayOf {
        /**
         * Faz a validação do tipo
         * @param mixed $value O valor que será validado
         * @return boolean
         */
        final protected function validate( $value ){
            $ret = false;
    
            if ( ( $type = gettype( $value ) ) == "boolean" ){
                $ret = true;
            } else {
                throw new UnexpectedValueException( sprintf( "ArrayOfBooleans aceita apenas valores lógicos, %s foi dado." , $type ) );
            }
    
            return( $ret );
        }
    }

Depois de criar as listas tipadas, o uso delas é exatamente igual a uma matriz normal:

 

    $nomes = new ArrayOfStrings();
    $nomes[] = "João";
    $nomes[] = "Neto";
    $nomes[] = "Teste";
    
    for ( $i = 0 , $t = $nomes->count() ; $i < $t ; $i++ ){
        printf( "O nome na posição %d é: %sn" , $i , $nomes[ $i ] );
    }
    
    $idades = new ArrayOfIntegers();
    $idades[] = 10;
    $idades[] = 20;
    $idades[] = 30;
    
    $precos = new ArrayOfDoubles();
    $precos[] = 10.0;
    $precos[] = 20.1;
    $precos[] = 30.3;
    
    $validos = new ArrayOfBooleans();
    $validos[] = true;
    $validos[] = false;
    $validos[] = true;

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.