Как реализовать полиморфизм в ростке?
Я разрабатываю приложение, которое включает в себя иерархию типов и начало с определения моделей для каждого типа посредством наследования. Когда дело доходит до написания соответствующих контроллеров, я не уверен, как правильно подойти ко всему этому. Должен ли я написать только один контроллер для базового типа, который может обрабатывать производные модели, или должен быть один контроллер для каждого подтипа? Как настроить привязки контроллера вида для работы с различными контроллерами?
4 ответа
Возможно, вы захотите проверить новую экспериментальную поддержку полиморфизма в SproutCore: http://groups.google.com/group/sproutcore-dev/browse_thread/thread/b63483ab66333d15
Обычно вы заполняете содержимое экземпляров ArrayController результатами вызовов App.store.find. SC.Store#find может принимать экземпляр SC.Query, который обычно выглядит следующим образом:
MyApp.myController.set('content') = MyApp.store.find(SC.Query.local(MyApp.MyModel));
Это должно вернуть все экземпляры MyApp.MyModel, включая все экземпляры подклассов MyApp.MyModel.
Первый аргумент в SC.Query.local может быть либо подклассом SC.Record, либо строкой, ссылающейся на подкласс. Поэтому, если у вас есть промежуточные подклассы SC.Record, вы можете попробовать использовать их там.
Вот некоторая информация об определении подклассов и переопределении свойств и методов: http://wiki.sproutcore.com/w/page/12412971/Runtime-Objects.
Из моего (ограниченного) использования Sproutcore я смог привязать только 1 вид к 1 контроллеру.
Таким образом, если вы планируете использовать одно представление (например, ListView) для отображения ваших данных, то я думаю, что вы сможете привязать это представление только к одному контроллеру. Это означает, что 1 базовый тип, который способен обрабатывать производные модели, кажется, путь.
Контроллеры должны быть просто прокси для объектов при работе с отдельными экземплярами вашей модели. Другими словами, ObjectController может прокси-сервер что угодно. Вот что я имею в виду в коде:
У вас есть два объекта, человек и студент.
App.Person = SC.Object.extend({
// person stuff here
})
App.Student = App.Person.extend({
// student stuff here, you have have all Person things because you are extending person.
})
Затем вы хотите определить контроллеры:
App.personController = SC.ObjectController.create({
contentBinding: 'App.path.to.person'
})
App.studentController = SC.ObjectController.create({
contentBinding: 'App.path.to.student'
})
обратите внимание, что вы можете связать содержимое контроллера с чем-то, только если человек / ученик является результатом выбора или какого-то другого потока, где срабатывает привязка. Другими словами, если вы установите человека вручную (скажем, из диаграммы состояний в результате взаимодействия), вы все равно определите контроллер, но сделаете
App.personController.set('content', person);
Вы настраиваете контроллер по-разному в зависимости от того, является ли Person объектом верхнего уровня в вашем приложении или каким-либо промежуточным объектом, который выбирается. Кроме того, вам может понадобиться только один контроллер, у вас будут только studentController и personController, если вы одновременно воздействуете на человека и студента. Оба являются просто ObjectControllers, и они могут прокси-все.
Наконец, по вашему мнению, вы должны связать соответствующий элемент представления с контроллером:
...
nameView: SC.LabelView.design({
layout: {/* props */},
valueBinding: SC.Binding.oneWay('App.personController.name')
})
...
обратите внимание, что односторонняя привязка заключается в том, что если имя не будет изменено в представлении, если представление может изменить имя, просто выполните обычную привязку. Также обратите внимание на путь здесь. Я не привязан к
'App.personController.content.name'
Так как personController проксирует объект, вы привязываетесь к
'namespace.controller.property-on-object-controller-proxies'
Если вы вкладываете много логики в свой контроллер, вы делаете это неправильно. Контроллеры должны быть только для прокси-объектов (по крайней мере, ObjectControllers). Бизнес-логика должна быть на самих моделях, а логика принятия решений должна быть в диаграммах состояний.