Структуры

Последнее обновление: 11.12.2023

Структура, как и класс, представляет тип, который определяется программистом и описывает состояние и поведение объектов. В этом плане структуры походят на классы, но они более подходят для опеделения небольших объектов, которые хранят небольшие данные или имеют простое поведение.

Структура имеет два способа определения. При первом тело структуры заключается между операторами struct и end:

type [модификатор_доступа] имя_структуры =
    struct
        компоненты структуры
    end

При втором способе применяется атрибут [<StructAttribute>]:

[<StructAttribute>]
type [модификатор_доступа] имя_структуры =
    компоненты структуры

Структуры, как и классы, могут иметь конструкторы, свойства, методы, поля, определяемые с помощью оператора val.

Но структуры не могут определять поля с помощью оператора let и также не могут определять выражений do, который выполняют некоторый код.

Определим простейшую структуру:

type Person = struct end	// определение структуры Person

let tom = Person		// определение значения структуры Person

Здесь определяется структура Person и далее определяется значение этой структуры. Причем в отличие от объектов классов для создания объекта структуры нам не обязательно определять конструктор.

Если структура имеет конструктор, то для всех его параметров надо явным образом указать тип данных:

type Person(name: string, age: int) = struct end

let tom = Person("Tom", 37)

В данном случае структура Person имеет конструктор с двумя параметрами, который можно использовать для создания объектов.

Как и классы, структуры могут определять дополнительные конструкторы:

type Person(name:string, age: int) = struct 
  
    new(name:string) = 
		printfn $"name: {name}"
        Person(name, 1)
end

При определении дополнительных конструкторов они также вызывают первичный конструктор.

Альтернативное определение структуры с помощью атрибута [<StructAttribute>]:

[<Struct>]
type Person(name:string, age: int) = 
    new(name:string) = 
        printfn $"name: {name}"
        Person(name, 1)

Методы в структрах

Структуры, как и классы, могут иметь методы, которые определяют поведение структуры:

type Person(name:string, age: int) = struct 
    
    member _.PrintPerson() = printfn $"Name: {name}  Age: {age}"
end

let tom = Person("Tom", 22)
tom.PrintPerson()   // Name: Tom  Age: 22

val-поля в структрах

Для хранения состояния в структрах можно использовать поля, определяемые с помощью оператора val:

type Person = struct 
    
    val mutable name: string
    val mutable age: int
end

let mutable tom = Person()
printfn $"Name: {tom.name}  Age: {tom.age}"     // Name:   Age: 0

tom.name <- "Tom"   // меняем значение поля name
tom.age <- 23     // меняем значение поля age

printfn $"Name: {tom.name}  Age: {tom.age}"     // Name: Tom  Age: 23

Стоит отметить, что если мы хотим менять значения полей структуры, то объект структуры тоже должен быть изменяемым. Так, в примере выше значение tom определено с ключевым словом mutable. Консольный вывод программы:

Name:   Age: 0
Name: Tom  Age: 23

И в этом случае действуют те же ограничения, что и при работе с классами. Так, если структура имеет первичный конструктор, то поля должны быть изменяемыми и иметь атрибут [<DefaultValue>]:

type Person(_name: string, _age: int) = struct 
    
    [<DefaultValue>]
    val mutable name: string
    [<DefaultValue>]
    val mutable age: int

    member this.SetValues() = 
        this.name <- _name
        this.age <- _age
end

let mutable tom = Person("Tom", 22)
printfn $"Name: {tom.name}  Age: {tom.age}"     // Name:   Age: 0

tom.SetValues()     // устанавливаем начальные значения
printfn $"Name: {tom.name}  Age: {tom.age}"     // Name: Tom  Age: 22
tom.age <- 25     // меняем значение поля age
printfn $"Name: {tom.name}  Age: {tom.age}"     // Name: Tom  Age: 25

Если первичного конструктора нет, но мы хотим передать им некоторые начальные значения, то нужно определить конструктор типа, который будет инициализировать эти поля:

type Person = struct 
    val name: string
    val mutable age: int

    new(_name:string, _age: int) = { name = _name; age=_age}
end

let mutable tom = Person("Tom", 22)
printfn $"Name: {tom.name}  Age: {tom.age}"     // Name: Tom  Age: 22

tom.age <- 23     // меняем значение поля age

printfn $"Name: {tom.name}  Age: {tom.age}"     // Name: Tom  Age: 23

Свойства в структрах

Также структуры могут иметь свойства:

type Person(name: string) = struct 
    
    member _.Name = name
    
    [<DefaultValue>]
    val mutable age: int

    member this.Age 
        with get() = this.age
        and set value = 
            this.age <- value

    member this.PrintPerson() = printfn $"Name: {this.Name}  Age: {this.Age}"
end

let mutable tom = Person("Tom")
tom.Age <- 24	// установка свойства
tom.PrintPerson()   // Name: Tom  Age: 24

Здесь структура Person имеет два свойства. Первое свойство - Name доступно только для чтения, оно получает начальное значение из первичного конструктора.

Второе свойство - Age использует для хранения значения поле age и доступно как для чтения, так и для записи.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850