|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
Как избежать копирования объекта при присвоении его в свойство класса? Такой вот кодClass test.clone Extends %RegisteredObject { Property stream As %Stream.Object; ClassMethod test() { write "test.clone.test:",!,! #dim stream as %Stream.TmpCharacter = ##class(%Stream.TmpCharacter).%New() #dim stream2 as %Stream.TmpCharacter = stream #dim obj as test.clone = ##class(test.clone).%New() set obj.stream = stream write "before:",! write "stream size:",stream.Size,! write "stream2 size:",stream2.Size,! write "obj.stream size:",obj.stream.Size,! write !,"write some data to stream...",!,! do stream.Write("Lorem ipsum dolor sit amet, consectetur adipiscing elit.") write "after:",! write "stream size:",stream.Size,! write "stream2 size:",stream2.Size,! write "obj.stream size:",obj.stream.Size,! write !,"write some data to obj.stream...",!,! do obj.stream.Write("Maecenas blandit dolor neque, ut malesuada lacus iaculis id.") write "after:",! write "stream size:",stream.Size,! write "stream2 size:",stream2.Size,! write "obj.stream size:",obj.stream.Size,! } } дает такой вот результат: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
Получается, что при присвоении объекта в свойство класса создается копия объекта, в то время как при присвоении объекта в локальную переменную копируется ссылка на объект? Если так, то как избежать копирования объекта при присвоении его в свойство класса? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 07:02 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
konstantin_11Получается, что при присвоении объекта в свойство класса создается копия объекта, в то время как при присвоении объекта в локальную переменную копируется ссылка на объект? Cloning Objects konstantin_11Если так, то как избежать копирования объекта при присвоении его в свойство класса?ЗаменитеТакой вот кодProperty stream As %Stream.Object;наТакой вот кодProperty stream As %ObjectHandle;Но в таком случае Вы сможете присваивать свойству любой OREF (не только на потомков класса %Stream.Object). ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 09:38 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
servitНо в таком случае Вы сможете присваивать свойству любой OREF (не только на потомков класса %Stream.Object). steamSet() решает эту проблему , нет?Class test.clone Extends %RegisteredObject { Property stream As %ObjectHandle; Method streamSet(val As %ObjectHandle) As %Status { set:(($isobject(val)) && (val.%IsA("%Stream.TmpCharacter"))) i%stream = val return $$$OK } /** do ##class(test.clone).test() **/ ClassMethod test() { write "test.clone.test:",!,! #dim stream as %Stream.TmpCharacter = ##class(%Stream.TmpCharacter).%New() #dim stream2 as %Stream.TmpCharacter = stream #dim proxy as %ZEN.proxyObject = ##class(%ZEN.proxyObject).%New() #dim obj as test.clone = ##class(test.clone).%New() set obj.stream = stream write "before:",! write "stream size:",stream.Size,! write "stream2 size:",stream2.Size,! write "obj.stream size:",obj.stream.Size,! write !,"write some data to stream...",!,! do stream.Write("Lorem ipsum dolor sit amet, consectetur adipiscing elit.") write "after:",! write "stream size:",stream.Size,! write "stream2 size:",stream2.Size,! write "obj.stream size:",obj.stream.Size,! write !,"write some data to obj.stream...",!,! do obj.stream.Write("Maecenas blandit dolor neque, ut malesuada lacus iaculis id.") write "after:",! write "stream size:",stream.Size,! write "stream2 size:",stream2.Size,! write "obj.stream size:",obj.stream.Size,! } /** do ##class(test.clone).test2() **/ ClassMethod test2() { write "test.clone.test:",!,! #dim stream as %Stream.TmpCharacter = ##class(%Stream.TmpCharacter).%New() #dim stream2 as %Stream.TmpCharacter = stream #dim proxy as %ZEN.proxyObject = ##class(%ZEN.proxyObject).%New() #dim obj as test.clone = ##class(test.clone).%New() set obj.stream = stream w "obj.stream type:",$classname(obj.stream),! set obj.stream = proxy w "obj.stream type:",$classname(obj.stream),! set obj.stream = "abc" w "obj.stream type:",$classname(obj.stream),! } } ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 15:38 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
И стоит добавить ещё обёртку SetSteam(val) As Status которая будет возвращать статус и работать уже через неё. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 15:45 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
eduard93servitНо в таком случае Вы сможете присваивать свойству любой OREF (не только на потомков класса %Stream.Object). steamSet() решает эту проблему , нет?Да, эту проблему решает, но не решает проблемы любого OREF, в том числе уже используемого другим объектом:Два разных объекта в памяти смотрят на один и тот же поток/// d ##class(test.clone).test3() ClassMethod test3() { write "test.clone.test3:",!,! #dim stream as %Stream.TmpCharacter = ##class(%Stream.TmpCharacter).%New() #dim obj1 as test.clone = ..%New() #dim obj2 as test.clone = ..%New() set obj1.stream = stream set obj2.stream = stream write "before:",! write "stream size:",stream.Size,! write "obj1.stream size:",obj1.stream.Size,! write "obj2.stream size:",obj2.stream.Size,! write !,"write some data to stream...",!,! do stream.Write("Lorem ipsum dolor sit amet, consectetur adipiscing elit.") write "after:",! write "stream size:",stream.Size,! write "obj1.stream size:",obj1.stream.Size,! write "obj2.stream size:",obj2.stream.Size,! write !,"write some data to obj1.stream...",!,! do obj1.stream.Write("Maecenas blandit dolor neque, ut malesuada lacus iaculis id.") write "after:",! write "stream size:",stream.Size,! write "obj1.stream size:",obj1.stream.Size,! write "obj2.stream size:",obj2.stream.Size,! }Если переопределять геттеры/сеттеры, то можно оставить свойству и изначальный тип:Property stream As %Stream.TmpCharacter; Method streamSet(val As %Stream.TmpCharacter) As %Status { s st=$$$OK if ($Isobject(val)) && (val.%IsA("%Stream.TmpCharacter")) { s r%stream = val }else{ s st=$$$ERROR($$$FormalArgTypeInvalid,$classname(val),"streamSet()","%Stream.TmpCharacter") } q st } eduard93И стоит добавить ещё обёртку SetSteam(val) As Status которая будет возвращать статус и работать уже через неё.Разве метода streamSet будет недостаточно? d $system.OBJ.DisplayError(obj.streamSet(proxy)) Код: plaintext
PS: впрочем, что нужно на самом деле ТС, знает только ТС, но наличие навыков работы с указателями в таком случае резко приветствуется. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 17:38 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
servitРазве метода streamSet будет недостаточно? Достаточно конечно, но лучше убрать возможность напрямую вызывать set obj.steam=x (по крайней мере из внешних классов):Class test.clone Extends %RegisteredObject { Property stream As %Stream.TmpCharacter [ Private ]; Method Setstream(val As %Stream.TmpCharacter) As %Status { return:'(($Isobject(val)) && (val.%IsA("%Stream.TmpCharacter"))) $$$ERROR($$$FormalArgTypeInvalid,$classname(val),"Setstream()","%Stream.TmpCharacter") s r%stream = val return $$$OK } }При проверке приведённого тут фрагмента обнаружилась проблема:set obj = ##class(test.clone).%New() do obj.Setstream("123") //нормально do obj.Setstream(123) // выдает ошибку <INVALID OREF>. Во втором случае пытается (как я понимаю) выполнить val.%IsA("%Stream.TmpCharacter") и выдает <INVALID OREF>. Почему?w $isobject(124) //0 w $isobject("124") //0 ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 18:53 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
eduard93Во втором случае пытается (как я понимаю) выполнить val.%IsA("%Stream.TmpCharacter") и выдает <INVALID OREF>. Почему?w $isobject(124) //0 w $isobject("124") //0Потому что w $classname("123") ;123 w $classname(123) ;<INVALID OREF> ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 20:07 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
servitПотому что w $classname("123") ;123 w $classname(123) ;<INVALID OREF> Но ведь вторая часть условия не должна выполняться, например выражение w (0 && $classname(123)) выведет 0 т.к. это short-circuit AND. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 20:58 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
eduard93Достаточно конечно, но лучше убрать возможность напрямую вызывать set obj.steam=x (по крайней мере из внешних классов)Лучше дождаться ТС, иначе можно нарефакторить вовсе ненужное. За основу можно взять метод %Library.CacheStream:Set(), который в итоге и используется по умолчанию. Он, кстати, выдаёт код $$$OrefInvalid, а не $$$FormalArgTypeInvalid, но это дело вкуса: Код: plaintext
... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 21:07 |
|
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
|
|||
---|---|---|---|
#18+
eduard93Но ведь вторая часть условия не должна выполняться, например выражение w (0 && $classname(123)) выведет 0 т.к. это short-circuit AND.Так она и не выполняется, но зато выполняется$$$ERROR($$$FormalArgTypeInvalid, $classname(val) ,"Setstream()","%Stream.TmpCharacter") ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2015, 21:10 |
|
|
start [/forum/topic.php?fid=39&msg=38919556&tid=1556695]: |
0ms |
get settings: |
11ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
35ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
49ms |
get tp. blocked users: |
1ms |
others: | 282ms |
total: | 414ms |
0 / 0 |