Upload
tobias
View
61
Download
2
Embed Size (px)
DESCRIPTION
Лекция 9 ПРОИЗВОДНЫЕ ТИПЫ. Производные типы, зачем ?. При сортировке используются перестановки элементов. Перестановка требует 3 операции присваивания . tmp = x(12) x(12) = x(15) x(15) = tmp Для перестановки двух частиц потребуется записать 21 (!) операции присваивания. - PowerPoint PPT Presentation
Citation preview
Лекция 9
ПРОИЗВОДНЫЕ
ТИПЫ
Производные типы, зачем ?
! данные N частицreal x(N)real y(N)real z(N)logical status(N)real temperature(N)real pressure(N)integer color(N)
При сортировкеиспользуются
перестановки элементов.
Перестановка требует 3 операции присваивания.
tmp = x(12) x(12) = x(15) x(15) = tmp
Для перестановки двух частиц потребуется
записать 21(!) операции присваивания.
Производные типы, зачем ?Лучше объединить типы под одним "общим типом“.
type particle real x ! координаты real y real z logical status real temperature ! физические real pressure ! параметрыinteger color ! цветend type particle
type (particle) M(N), tmp... tmp = M(12) ! 3 присваивания M(12) = M(15) M(15) = tmp
поля
Оператор type
Объявляет новый тип данных,группируя под одним именем существующие типы.
type имя
типы данных
contains
процедуры привязанные к типу
end type имя
Операция " . " или " % ".
Доступ к полям
Задание начальных значений для каждого поля лучше с использованием конструктора.
program prog type NewType integer A real B character C logical D end type NewType
type (NewType) PS
PS.A = 35; PS.B = 3.14; PS.C = 'E'; PS.D = .FALSE. PS%A = 25; PS%B = 5.67; PS%C = 'Q'; PS%D = .TRUE.
end
Конструктор производного типа
program prog type NewType integer A real B character C logical D end type NewType
type (NewType) :: PS0 = NewType(1, 0.32, 'Z', .FALSE.) type (NewType) PS1 type (NewType), allocatable :: PS2
PS1 = NewType(5, 3.5, 'Q', .TRUE.)
allocate(PS2); PS2 = NewType(8, 1.2, 'F', .TRUE.) ! ИЛИ allocate(PS2, source = NewType(8, 1.2, 'F', .TRUE.)) write(*,*) PS2 ! вывод значений всех полейend
конструктор
Конструктор – функция с именем производного типа. Параметры функции - поля производного типа.
Иерархия типовtype person character(128) fio integer ageend type person
type firm type (person) people(1000) character(128) name integer moneyend type firm
type (firm) FM
FM.money = 100000 ! доступ к полямFM.name = 'Siberia'FM.people(1).fio = 'Ivanov S.K.'FM.people(1).age = 35
type PARENT ! родитель integer A real Bend type PARENT
type, extends (PARENT) :: CHILD ! потомок character Cend type CHILD
type (CHILD) pas1, pas2
pas1 = CHILD(PARENT(1,2.0),'A')pas2 = CHILD(1,2.0,'A')
Расширение типа, extends
Тип CHILD наследует поля типа PARENT
Оператор classClass объявляет полиморфную переменную.
Если полиморфная переменная не является формальным параметром процедуры, то
используются атрибуты allocatable или pointer.
class (имя производного типа), allocatable :: имя
type PARENT integer A real B end type PARENT type, extends (PARENT) :: CHILD ! наследуем тип PARENT character C end type CHILD type (CHILD), allocatable :: CL1 class (CHILD), allocatable :: CL2 allocate(CL1, source = CHILD(1,3.0,'Q')) allocate(CL2, source = CHILD(1,3.0,'Q'))
Переменная CL2 имеет больше возможностей.
Полиморфная переменная объявленная родительским типом может "принимать" все дочерние типы.
Оператор class
program prog type PARENT integer A real B end type PARENT
type, extends (PARENT) :: CHILD_A character C end type CHILD_A
type, extends (PARENT) :: CHILD_B logical D end type CHILD_B
type, extends (CHILD_A) :: CHILD_CHILD_A complex E end type CHILD_CHILD_A
Оператор classclass (PARENT), pointer :: PAR
type (PARENT), target :: P type (CHILD_A), target :: CA type (CHILD_B), target :: CB type (CHILD_CHILD_A), target :: CCA
PAR => P ! стал родителем PAR => CA ! теперь потомок А PAR => CB ! изменился на потомка B PAR => CCA ! теперь потомок потомка А
end
PARENT
CHILD_A
CHILD_B
CHILD_CHILD_A
Конструкция select typeКак определить какой тип имеет
полиморфная переменная ?
Select type позволяет выполнить блок операторов в зависимости от динамического типа полиморфной
переменной.
select type (переменная)
type is (имя типа)
class is (имя типа)
class default
end select
Оператор select type
Схема выполнения
Находится и выполняется блок type is
Если не найден type is, то находится и выполняется class is.
Если найдено соответствие нескольким блокам class is, то выбирается ближайший родитель.
Если не найден ни один блок выбирается class default.
Оператор select type... type (PARENT), target :: P type (CHILD_CHILD_A), target :: CCA PAR => CCA ! потомок потомка А
select type (PAR) class is (PARENT) write (*,*) "PARENT"
class is (CHILD_A) write(*,*) "CHILD" ! выбирается ближайший родитель
class default write(*,*) "default...." end select end
PARENTCHILD_A
CHILD_B
CHILD_CHILD_A
Оператор class(*)Неограниченно полиморфная переменная
принимает любые типы
type T1 integer index real val end type T1
type T2 logical status character symbol character(10) name end type T2
complex(16), target :: CMP type (T1), target :: PT1 type (T2), target :: PT2
class (*), pointer :: PAR ! неограниченно полиморфная
PAR => PT1 ! сейчас типа T1 PAR => PT2 ! теперь типа T2 PAR => CMP ! затем комплексный тип
procedure(proc), pointer :: p1 => null()
Процедурные указатели
type NewType integer a real b contains procedure proc1 procedure :: proc2 => other_prend type NewType ...
call A.proc1(a,b)
Procedure описывает процедурный указатель, позволяет добавлять процедуры в созданный тип.
Атрибуты pass и nopass
Используются для процедур привязанных к производному типу по имени.
pass позволяет получить доступ к переменной, посредством которой вызывалась процедура
(по умолчанию).
Вызывающая переменная записывается в процедуре, первым параметром и должна быть объявлена
оператором class.При вызове процедуры данный параметр опускается.
nopass отменяет доступ к вызывающей переменной.
Процедуры привязанные к типу
module algebra type, public :: vector real x1, y1, x2, y2
contains procedure, public, pass :: length procedure, nopass :: info end type vector CONTAINS
subroutine info() write(*,*) "I'am VECTOR" end subroutine info
integer function length(vc) ! атрибут pass class(vector) vc length = sqrt((vc.x1-vc.x2)**2 + (vc.y1-vc.y2)**2) end function lengthend module algebra
Процедуры привязанные к типу
program prog
use algebra
class (vector), allocatable :: VEC
allocate(VEC, source = vector(0.0,0.0,3.0,4.0))
call VEC.info()
write(*,*) VEC.length() ! формальный параметр отсутствует ! однако при описании объявлен
deallocate(VEC)
end
type NewType...contains final :: finishend type NewType
Завершающие процедуры
Оператор final объявляет процедуры (деструкторы), которые выполняются при удалении
ранее размещенных в памяти элементов
module MyModule... type NewType integer A real, private :: B integer C real, private :: D end type NewType...end module MyModule
Атрибут privateИспользуется для задания отдельных полей
производных типов в модулях. Доступ к приватной части происходит при помощи public-процедур.
module MyModule
type NewType integer A real, private :: B contains procedure :: SetParamB end type NewType
contains subroutine SetParamB(T,newvalue) class(NewType) T real newvalue if (newvalue < 0) then write(*,*) "Error in parameter B, must be >=0" T.B = 0 else T.B = newvalue end if end subroutineend module
Атрибут private (Пример)
program prog use MyModule class(NewType), allocatable :: nw allocate(nw) nw.A = 1000 !nw.B = 4.5 ! ошибка доступа call nw.SetParamB(4.5)
call nw.SetParamB(-9.4) ! некорректные данные
end
Атрибут private (Пример)
Перегрузка операцийНабросок модуля арифметики длинных чисел.
module long
type LongNumbe integer(1) val(length) ! цифры integer total ! количествоend type LongNumber
contains subroutine asgn(n,val) ! присваивание ! операторы end subroutine asgn function plus(n1,n2) ! операция сложение и другие ! операторы end function plus subroutine PrintLong(n) ! вывод числа ! операторы end subroutine PrintLongend module long
Набросок вызывающей программы
program prog use long type (LongNumber) a, b, c, d
call asgn(a,"2823892839283923837483485555555") call asgn(b,"92882746") call asgn(c,"2038493849300000")
!---- хотим найти выражение ! d = a*(b+c)+c*(a+b)+b d = plus(plus(umn(a,plus(b,c)),umn(c,plus(a,b))),b) ! очень громоздкая запись ! осложнение если будет много операций
call PrintLong(d)end
Перегрузка операций
Перегрузка операций
Перегрузка операции присваивания
interface assignment (=) module procedure asgn ! имя процедуры end interface
Перегрузка операции сложения, умножения и др.
interface operator (+) module procedure plus ! имя процедуры end interface
Замена имени процедуры на знак операции.
Перегрузка операций
Унарная операция - функция с одним входным параметром имеющего вид связи IN.
Двуместная операция - функция с двумя параметрами имеющими вид связи IN.
Нельзя изменять тип встроенной операции. (например '*' оформить как унарную).
Процедура, задающая '=' должна быть подпрограммой с двумя параметрами.
1-й вид связи OUT или INOUT (левая часть),2-й параметр IN (правая часть).
Задаваемые операции
Вводятся аналогично унарным и двуместным операциям.
Имя операции задаётся по общим правилам.
В выражениях операция ограничивается точками.
interface operator (.PLUS.) module procedure plus end interface
...
SUMMA = A.PLUS.B
Приоритет операций
унарная перегруженная или задаваемая операция
арифметические операции
символьная операция конкатенация
операции отношения
логические операции
задаваемая или перегруженная бинарная операция
Создать модуль для работы с длинными числами. Реализовать операции присваивания, сложения и
вывода длинных целых чисел.
* З а д а н и е *