Создать класс с несколькими проиндексированными свойствами

Я пытаюсь создать класс с несколькими свойствами, которые индексируются тем же номером, который я передаю в свойство. Я пробовал несколько конфигураций кода, моя последняя ошибка заключалась в следующем:

'dataTypeClass class module
Private ap() As String
Private dt() As String

Public Property Get apos(index As Long) As Variant
Set apos = ap(index)
End Property

Public Property Get dataType(index As Long) As Variant
Set dataType = dt(index)
End Property

Public Property Let apos(index As Long, apVal As String)
ap(index) = apVal
End Property

Public Property Let dataType(index As Long, dtVal As String)
dt(index) = dtVal
End Property

В основном я получаю этот код ошибки:

Создать класс с несколькими проиндексированными свойствами

Ожидается использование ниже, чтобы получить "INT" и "" для пункта 1 в подпункте ниже.

Sub classTest()

Dim d As New dataTypeClass
d(1).dataType = "INT"
d(1).apos = ""
Debug.Print d(1).dataType & d(1).apos
End Sub

Что я делаю неправильно?

Обновлено: Принимая приведенные ниже предложения (например, редактируя свой вопрос, а не комментируя), я устанавливаю варианты в виде строк и использую let вместо set. Поскольку я действительно получил индекс вне допустимого диапазона, мне нужно инициализировать класс, но нужен ли мне redim index? Как я могу это сделать, если каждый раз при запуске скрипта индекс будет иметь другой максимум?

BigBen поднимает хороший вопрос: ваши массивы не инициализируются, поэтому присвоение индексу приведет к ошибке 9 / index out of bounds - если вы просто не пропустили обработчик Class_Initialize, который их инициализирует.

Mathieu Guindon 14.12.2018 20:15

Также указано в комментарии ниже, но d(1).dataType и d(1).apos должны быть d.dataType(1) и d.apos(1).

BigBen 14.12.2018 20:19

RE: Ваше последнее редактирование - это полностью зависит от вашей реализации. Здесь никто не знает, как вы собираетесь использовать этот класс и для чего он нужен. Но если вы не знаете, сколько элементов вам понадобится, рассмотрите возможность инкапсуляции Collection вместо массива.

Mathieu Guindon 14.12.2018 20:33

@JohnyL, это правда, но совершенно не имеет отношения к этому вопросу и еще больше сбивает с толку ОП.

Mathieu Guindon 14.12.2018 20:50

@JohnyL попробуйте public string Foo { get { return _foo; } int set { _foo = value; } } на C#, расскажите, как это происходит.

Mathieu Guindon 14.12.2018 21:02

Синтаксическая ошибка @MathieuGuindon

JohnyL 14.12.2018 21:06

@JohnyL IKR! Перегрузка методов тоже не любит конфликтующих типов! Вы не можете иметь int Foo() { return 42; } и string Foo() { return "42"; } и вызывать эту перегрузку метода.

Mathieu Guindon 14.12.2018 21:10

@MathieuGuindon Я не понял, что вы пытались сказать, но я только что понял, что моя заметка о перегрузке не имеет ничего общего с вопросом. ))

JohnyL 14.12.2018 21:12
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
1
8
88
2

Ответы 2

У вас есть вариант для возвращаемого типа вашего Get, но ваш дополнительный параметр Let использует строку. Может вам нужен dtVal As Variant? Как упоминалось в комментариях и другом ответе, есть дополнительные вещи, которые следует учитывать; некоторые будут зависеть от реализации.

Цитировать:

The parameters for Property Get, Property Let, and Property Setprocedures for the sameproperty must match exactly, except that the Property Let has one extra parameter, whose type must match the return type of the corresponding Property Get, and the Property Set has one more parameter than the corresponding Property Get, whose type is either Variant, Object, a class name, or an object library type specified in an object library. This error has the following causes and solutions:

The number of parameters for the Property Get procedure isn't one less than the number of parameters for the matching Property Let or Property Set procedure. Add a parameter to Property Let or Property Set or remove a parameter from Property Get, as appropriate.

The parameter types of Property Get must exactly match the corresponding parameters of Property Let or Property Set, except for the extra Property Set parameter. Modify the parameter declarations in the corresponding procedure definitions so they are appropriately matched.

The parameter type of the extra parameter of the Property Let must match the return type of the corresponding Property Get procedure. Modify either the extra parameter declaration in the Property Let or the return type of the corresponding Property Get so they are appropriately matched.

The parameter type of the extra parameter of the Property Set can differ from the return type of the corresponding Property Get, but it must be either a Variant, Object, class name, or a validobject library type.

Make sure the extra parameter of the Property Set procedure is either a Variant, Object, class name, or object library type.

You defined a Property procedure with an Optional or a ParamArray parameter. ParamArray and Optional parameters aren't permitted in Property procedures. Redefine the procedures without using thesekeywords.

Также необходимо избавиться от Set в Set apos = ap(index) и Set dataType = dt(index).

BigBen 14.12.2018 19:48

Это Private ap() As String и Private dt() As String (не As Variant), поэтому я предполагаю, что тип возврата Property Get должен быть As String, верно?

BigBen 14.12.2018 19:50

Также понадобится помощь с этими нераспределенными массивами и classTest. d(1).dataType предположительно должен быть d.dataType(1) = "INT", но выдает нижний индекс за пределы допустимого диапазона ...

BigBen 14.12.2018 19:58

Да ... спасибо. Я заметил несколько вещей, в том числе проблему использования set as is. Но, к счастью, мы с Мэттом также занимаемся этим делом!

QHarr 14.12.2018 20:35

Я тоже. Ржу не могу. :-)

QHarr 14.12.2018 20:37

Свойство apos1 получает Variant по указанному index; реализация предполагает, что инкапсулированный ap(index) - это Object, поэтому тип возврата, вероятно, должен быть Object вместо Variant:

Public Property Get apos(index As Long) As Variant
Set apos = ap(index)
End Property

Установщик использует назначение Let, что является хакерским, но разрешено, учитывая значение Variant - о, подождите, нет, это String!

Public Property Let apos(index As Long, apVal As String)
ap(index) = apVal
End Property

Вы получаете эту ошибку, потому что, как указано в ошибке, определение свойства несовместимо. Если ap(index) - это String, то получатель должен выглядеть так:

Public Property Get apos(index As Long) As String
apos = ap(index)
End Property

Если ap(index) - это Object, то сеттер должен выглядеть так:

Public Property Set apos(index As Long, apVal As Object)
Set ap(index) = apVal
End Property

... и получатель вроде этого:

Public Property Get apos(index As Long) As Object
Set apos = ap(index)
End Property

Или вот так:

Public Property Get apos(index As Long) As Variant
Set apos = ap(index)
End Property

Public Property Set apos(index As Long, apVal As Variant)
Set ap(index) = apVal
End Property

Другими словами:

  • Параметр RHS / значение Property Let / Property Set должен быть того же типа, что и тип возвращаемого значения одноименного члена Property Get.
  • Если тип является типом объекта, используйте Property Set для назначений.
  • Если тип является типом значения, используйте Property Let для назначений.
  • По возможности избегайте Variant.
  • Не используйте Set для назначения чего-либо, кроме ссылки на объект.

1 Все это верно и для свойства dataType.

Когда я увидел название этого вопроса, я подумал про себя: «Ой, смотри, он играет песню Мэтта». Хорошая шапка.

TinMan 15.12.2018 09:13

Другие вопросы по теме