Pergunta

É possível, no momento, para substituir a estrutura construtor em Fortran?Eu tenho visto proposta de exemplos como este (como no Fortran 2003 spec):

module mymod

  type mytype
    integer :: x
    ! Other stuff
  end type

  interface mytype
    module procedure init_mytype
  end interface

contains
  type(mytype) function init_mytype(i)
    integer, intent(in) :: i
    if(i > 0) then
      init_mytype%x = 1
    else
      init_mytype%x = 2
    end if
  end function
end

program test
  use mymod
  type(mytype) :: x
  x = mytype(0)
end program

Basicamente, isso gera um monte de erros devido ao redundante de nomes de variáveis (e.g.Erro:Atributo DERIVADO de 'mytype, os conflitos com o PROCEDIMENTO de atributo (1)).Uma cópia textual do fortran 2003 exemplo gera erros semelhantes.Eu tentei isso no git 4.4, ifort 10.1 e 11.1 e todos eles produzem os mesmos erros.

Minha pergunta:este é apenas um unimplemented recurso do fortran 2003?Ou sou eu que a implementação deste incorretamente?

Editar:Eu vim através de um relatório de bug e um anunciou patch para git em relação a este problema.No entanto, tentei usar um de novembro de compilação do gcc46 com sorte e erros similares.

Edit 2:O código acima parece funcionar usando Intel Fortran 12.1.0.

Foi útil?

Solução

Consultei a minha cópia do Fortran 2008 standard.Que não permite que você defina uma interface genérica com o mesmo nome como um tipo derivado.Meu compilador Intel Fortran 11.1) não compilar o código que assim que eu fico suspeitando (sem uma cópia de 2003 standard para a mão) que este é um ainda não implementados recurso do Fortran 2003 standard.

Além disso, há um erro em seu programa.Sua declaração de função:

  type(mytype) function init_mytype
    integer, intent(in) :: i

especifica a existência e a intenção de um argumento que não está presente na especificação da função, que deve, talvez, ser reescrito como:

  type(mytype) function init_mytype(i)

Outras dicas

É possível, no momento, para substituir a estrutura construtor em Fortran?

Não. De qualquer forma, mesmo usando a sua abordagem é completamente não sobre o construtor de substituir.A principal razão é que a estrutura construtor # OOP construtor.Existe alguma semelhança, mas esta é apenas uma outra idéia.

Você não pode usar sua não-função intrínseca na expressão de inicialização.Você pode usar apenas constante, matriz ou estrutura de construtor, funções intrínsecas, ...Para mais informações, dê uma olhada no item 7.1.7 expressão de Inicialização no Fortran 2003 rascunho.

Levando esse fato em consideração, eu completamente não entendem qual é a real diferença entre

type(mytype) :: x
x = mytype(0)

e

type(mytype) :: x
x = init_mytype(0)

e qual é o ponto de todo usando a INTERFACE bloco dentro mymod MÓDULO.

Bem, para ser honesta, há uma diferença, o grande - a primeira maneira é enganosa.Esta função não é o construtor (porque não há nenhuma OOP construtores em todos os Fortran), é um inicializador.


No mainstream OOP construtor é responsável por sequencialmente fazer duas coisas:

  1. A alocação de memória.
  2. Inicialização de membro.

Vamos dar uma olhada em alguns exemplos de instanciação de classes em linguagens diferentes.

No Java:

MyType mt = new MyType(1);

um fato muito importante é oculto - o fato de o objeto é na verdade um ponteiro para um varibale de um tipo de classe.O equivalente em C++ vai ser a alocação de heap usando:

MyType* mt = new MyType(1);

Mas em ambos os idiomas, pode-se ver que dois construtor deveres são reflete-se ainda na sintaxe de nível.Ele consiste em duas partes:nova palavra-chave (alocação) e construtor (nome de inicialização).No Objective-C sintaxe este fato é ainda mais enfatizada:

MyType* mt = [[MyType alloc] init:1];

Muitas vezes, no entanto, você pode ver alguma outra forma de construtor de invocação.No caso de a alocação de pilha C++ usos especiais (muito pobre) a sintaxe de construção

MyType mt(1);

que, na verdade, é tão enganosa que podemos considerar.

No Python

mt = MyType(1)

tanto o fato de que o objeto é, na verdade, um ponteiro e o fato de que a alocação de tomar o primeiro lugar estão ocultos (na sintaxe de nível).E esse método é chamado de ... __init__!O_O Tão enganosa.С++ alocação de pilha desaparece em comparação com aquele.=)


De qualquer maneira, a idéia de ter construtor na língua implica a capacidade de fazer alocação de uma inicialização em uma instrução usando algum tipo especial de método.E se você acha que isso é "OOP verdadeiro" caminho eu tenho más notícias para você.Mesmo Smalltalk não tem construtores.É apenas uma convenção para ter um new método em classes de si (eles são objetos singleton de meta-classes).O Fábrica Padrão De Design é usado em muitos outros idiomas para atingir o mesmo objetivo.

Eu li em algum lugar que os conceitos de módulos na linguagem Fortran foi inspirado Modula-2.E parece para mim que a OOP recursos são inspirados por Oberon-2.Não há construtores em Oberon-2 também.Mas há, claro, puro alocação com predeclared procedimento de NOVO (como ALOCAR em Fortran, mas é ALOCAR instrução).Após a alocação você pode (deve, na prática) chamar alguns inicializador, que é apenas uma ordinária método.Nada de especial por lá.

Assim, você pode usar algum tipo de fábricas para inicializar objetos.É o que você realmente fez uso de módulos em vez de objetos singleton.Ou é melhor dizer que eles (Java/C#/...programadores) utilizar objetos singleton métodos em vez de comum funções devido à falta de um outro, posterior (sem módulos - de jeito nenhum ter ordinária funções, apenas métodos).

Você também pode usar o tipo vinculado a sub-ROTINA em vez disso.

MODULE mymod

  TYPE mytype
    PRIVATE
    INTEGER :: x
    CONTAINS
    PROCEDURE, PASS :: init
  END TYPE

CONTAINS

  SUBROUTINE init(this, i)
    CLASS(mytype), INTENT(OUT) :: this
    INTEGER, INTENT(IN) :: i

    IF(i > 0) THEN
      this%x = 1
    ELSE
      this%x = 2
    END IF
  END SUBROUTINE init

END

PROGRAM test

  USE mymod

  TYPE(mytype) :: x

  CALL x%init(1)

END PROGRAM

INTENT(OUT) para this arg de init Sub-ROTINA parece ser bom.Porque esperamos que este método a ser chamado apenas uma vez e logo depois de alocação.Pode ser uma boa idéia para controlar o que esta suposição não será errado.Para adicionar algum sinalizador booleano LOGICAL :: inited para mytype, verifique se é .false. e defina-o para .true. após a primeira inicialização, e fazer algo a mais na tentativa de re-inicialização.Eu, definitivamente, lembre-se de alguns thread sobre isso em Google Groups...Eu não posso encontrá-lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top