Свойства

Свойства - это некоторые значения, хранящиеся в классах/объектах, и описывающие их.
Набор свойств, имеющийся у конкретной сущности, задается в классах, от которых данная сущность наследуется.

Пример использования свойств

class Cat {
	//свойство "возраст" целочисленного типа,
	// определенное для объектов класса "кот"
	obj prop age: int[0, 100] ;
}

obj Basya : Cat {
	//Конкретное значение свойства "возраст", присущее объекту "Бася" класса "кот"
	age = 2 ;
}

В коде определения свойств представлены классом PropertyDef
Состав базовой хранимой информации:

  • Имя свойства (PropertyDef.name)
  • Имя класса, объявившего свойство (PropertyDef.declaringClassName)
  • Тип значения свойства (PropertyDef.type)
  • Вид свойства (PropertyDef.kind)
  • Связанные со свойством метаданные (PropertyDef.metadata)

Утверждения о значении свойств представлены классом PropertyValueStatement
Состав базовой хранимой информации:

  • Сущность, которой принадлежит значение - класс/объект (PropertyValueStatement.owner)
  • Имя свойства (PropertyValueStatement.propertyName)
  • Задаваемое значение свойства (PropertyValueStatement.value)

Объектные и классовые свойства

В системе есть разграничения между объектными и классовыми свойствами. Как следует из названия, это различие определяет, какой сущности могут принадлежать свойства - классам или объектам.
Для аналогии можно опять же вспомнить Java - классовые свойства похожи на static поля, т.к. принадлежат классам. Объектные же свойства аналогичны обычным полям, т.к. принадлежат отдельным объектам и разнятся от объекта к объекту

Соответственно, значение свойства можно определять только в сущности, соответствующей виду данного свойства

Пример использования различных видов свойств

//класс "Животное"
class Animal {
	//свойство "является разумным" является классовым,
	// а то есть принадлежит классу и определяется в нем -
	// поскольку это свойство не может разниться 
	// от одного животного к другому внутри одного класса 
	class prop isSentient : bool = false ;

	//свойство "возраст" является объектным,
	// а то есть принадлежит объектам класса и определяется в них -
	// поскольку это свойство может разниться от одного животного к другому
	obj prop age: int[0, 100] ;
}

//класс "Человек", наследуется от "Животного"
class Human : Animal {
	//В отличие от static-полей в Java, классовые свойства в нашей системе
	// могут наследоваться и переопределяться в классах наследниках.
	//Так, "Человек" переопределяет для своих объектов свойство "является разумным"
	isSentient = true ;
}

//объект "Петя", инстанс класса "Человек"
obj Petya : Human {
	//значение объектного свойства определяется в объекте
	age = 20 ;
}

Получение значений свойств

Значения свойств, вне зависимости от их вида и типа, наследуются и могут переопределяться - это можно видеть в примере выше.

На практике это значит, что процесс получения значения свойства для текущей сущности происходит по следующему простому принципу:

  1. Пока значение не найдено:
    1. Если текущая сущность определяет значение свойства, вернуть его
    2. Иначе перейти к родительскому классу текущей сущности

(Именно так реализован код в методе ClassInheritorDef.getPropertyValue())

Из этого следует, что с помощью наследования в конкретном объекте можно получить значения свойств, определенных в самом этом объекте или в его родительских классах (т.к. они наследуются)
При этом, конечно, стоит учитывать ограничения, описанные в предыдущем разделе - так, значение объектного свойства можно найти только в самом объекте, а вот значение классового свойства можно быть получено только из его родительских классов.

Типы значений свойств

Любое свойство обязано указывать тип своего значения (поле PropertyDef.type).
Свойства могут иметь следующие типы:

  • Булево значение, BooleanType
  • Целые числа, IntegerType
  • Дробные числа, DoubleType
  • Строки, StringType
  • Перечисления EnumType

Это обусловлено тем, что только данные типы считаются в системе "примитивными", поскольку они не взаимодействуют с объектной стороной системы (в отличие от типов ClassType и ObjectType) - возможность "запихнуть" в значение свойства объект или класс нарушала бы принципы системы. Для подобного связывания между объектами есть отношения.

Параметризация

TODO

Корректность данных (валидация)

Полнота

Класс, объявляющий свойство (PropertyDef.declaringClassName), должен присутствовать в модели.

В случае, если свойство имеет перечислимый тип (enum), то заданное перечисление должно присутствовать в модели.

Для утверждения о значении свойства, данное свойство должно присутствовать в модели.

Валидность

Свойство, объявленное в конкретном классе, не может иметь имя, повторяющее имя одного из свойств, уже определенных в классе или его классах-родителях.

Значения классовых свойств должны быть определены только в классах, а объектных - в объектах.

Тип значения свойства должен соответствовать объявленному типу свойства.

В случае, если класс является конкретным (в модели существуют объекты, являющиеся прямыми инстансами этого класса), то в нем должны быть определены значения для всех классовых свойств, указанных в нем и его родительских классах (с учетом наследования их значений).
Т.е. не допускается ситуация, когда какой-то объект наследуется от класса, но при этом в цепочке наследования для этого объекта не определено какое-то из свойств класса.