definicion caracteristicas oop polymorphism fortran

oop - caracteristicas - polimorfismo en tiempo de ejecución en Fortran 2003



fortran definicion (2)

Estoy escribiendo un código en Fortran 2003 que hace una gran cantidad de álgebra lineal con matrices dispersas. Estoy intentando explotar algunas de las características más abstractas del nuevo estándar, así que tengo programas más simples sin demasiados códigos repetidos.

Tengo un solver procedimientos que toma en una matriz, algunos vectores, la tolerancia para el método iterativo utilizado, etc. Le paso un puntero a un procedimiento llamado matvec ; matvec es la subrutina que usamos para las multiplicaciones de matrices-vectores.

El problema es que, a veces, matvec es un procedimiento que colorlist, color1, color2 argumentos adicionales colorlist, color1, color2 encima de los habituales enviados a este procedimiento. Puedo pensar en varias formas de lidiar con esto.

Primera idea: definir dos interfaces abstractas diferentes matvec1 , matvec2 y dos solucionadores diferentes. Esto funciona, pero significa duplicar código, que es exactamente lo que trato de evitar.

Otra idea: mantener la misma interfaz abstracta matvec , y hacer que los argumentos adicionales colorlist , color1 , color2 opcionales. Eso significa hacerlos opcionales en cada rutina matvec, incluso aquellos para los que no son realmente opcionales, y para rutinas donde ni siquiera se usan. Estoy bastante seguro de que iré al infierno si hago esto.

Puedo pensar en muchas otras soluciones menos que óptimas. Me gustaría obtener alguna opinión sobre esto, estoy seguro de que hay una forma elegante de hacerlo, solo que no estoy seguro de qué se trata.


En lugar de pasar el puntero de procedimiento como un argumento explícito, podría poner las diversas rutinas matvec detrás de una interfaz genérica:

interface matvec module procedure matvec1, matvec2 end interface

Entonces su rutina de solver puede simplemente usar el nombre genérico con o sin los argumentos adicionales. Por supuesto, también se puede tomar el mismo enfoque cuando se usa el enfoque sugerido de Bálint para definir un solver como un tipo derivado con procedimientos de tipo ligado:

type :: solver real, allocatable :: matrix(:,:), v1(:), v2(:) contains procedure, pass :: matvec1 procedure, pass :: matvec2 generic :: matvec => matvec1, matvec2 end type

La diferencia principal es que esto no usa polimorfismo para determinar el procedimiento correcto para invocar, sino más bien las características de los argumentos ficticios.

No estoy seguro de sus intenciones para el puntero del procedimiento; si desea cambiar su objetivo en el tiempo de ejecución (o tal vez asignar algún significado especial a su estado "indefinido"), los punteros son la única forma y todos los objetivos deben coincidir con la misma interfaz abstracta. Si, en cambio, solo necesitas seleccionar uno de varios procedimientos basados ​​en sus argumentos, entonces puedes explotar la interfaz (mi ejemplo) o la sobrecarga (ejemplo de Bálint). Cada extensión de un tipo puede extender un enlace generic heredado con nuevos procedimientos o sobrecargar un enlace específico heredado.


La pregunta es, realmente, si los argumentos adicionales se deben pasar cada vez que se invoca el procedimiento (porque cambian entre dos invocaciones), o pueden inicializarse en algún momento y luego usarse en la función. En el caso posterior, podría crear una clase con una interfaz abstracta, que defina su subrutina matvec con los argumentos esenciales. Luego puede extender esa clase con otras más especializadas, que pueden contener las opciones adicionales necesarias. Aún tendrán que definir la misma interfaz matvec que la clase padre (con la misma lista de argumentos), pero pueden usar los valores adicionales almacenados en ellos cuando se matvec su procedimiento matvec .

Encontrará un ejemplo detallado en esta respuesta para un caso similar (busque el segundo ejemplo que muestra el module rechercheRacine ).