powered by simpleCommunicator - 2.0.37     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
10 сообщений из 10, страница 1 из 1
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38918348
konstantin_11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как избежать копирования объекта при присвоении его в свойство класса?
Такой вот код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.
USER>do ##class(test.clone).test()
test.clone.test:
 
before:
stream size:0
stream2 size:0
obj.stream size:0
 
write some data to stream...
 
after:
stream size:56
stream2 size:56
obj.stream size:0
 
write some data to obj.stream...
 
after:
stream size:56
stream2 size:56
obj.stream size:60

Получается, что при присвоении объекта в свойство класса создается копия объекта, в то время как при присвоении объекта в локальную переменную копируется ссылка на объект? Если так, то как избежать копирования объекта при присвоении его в свойство класса?
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38918448
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
konstantin_11Получается, что при присвоении объекта в свойство класса создается копия объекта, в то время как при присвоении объекта в локальную переменную копируется ссылка на объект? Cloning Objects konstantin_11Если так, то как избежать копирования объекта при присвоении его в свойство класса?ЗаменитеТакой вот кодProperty stream As %Stream.Object;наТакой вот кодProperty stream As %ObjectHandle;Но в таком случае Вы сможете присваивать свойству любой OREF (не только на потомков класса %Stream.Object).
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38919223
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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),!
}

}
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38919238
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И стоит добавить ещё обёртку SetSteam(val) As Status которая будет возвращать статус и работать уже через неё.
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38919395
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
ОШИБКА #5500: %ZEN.proxyObject тип формального аргумента streamSet() неверен : %Stream.TmpCharacter

PS: впрочем, что нужно на самом деле ТС, знает только ТС, но наличие навыков работы с указателями в таком случае резко приветствуется.
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38919476
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38919530
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard93Во втором случае пытается (как я понимаю) выполнить val.%IsA("%Stream.TmpCharacter") и выдает <INVALID OREF>. Почему?w $isobject(124) //0
w $isobject("124") //0Потому что w $classname("123") ;123
 w $classname(123) ;<INVALID OREF>
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38919556
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servitПотому что w $classname("123") ;123
 w $classname(123) ;<INVALID OREF>
Но ведь вторая часть условия не должна выполняться, например выражение w (0 && $classname(123)) выведет 0 т.к. это short-circuit AND.
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38919566
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard93Достаточно конечно, но лучше убрать возможность напрямую вызывать set obj.steam=x (по крайней мере из внешних классов)Лучше дождаться ТС, иначе можно нарефакторить вовсе ненужное.
За основу можно взять метод %Library.CacheStream:Set(), который в итоге и используется по умолчанию.
Он, кстати, выдаёт код $$$OrefInvalid, а не $$$FormalArgTypeInvalid, но это дело вкуса:

Код: plaintext
ОШИБКА #5807: Недопустимый OREF 'bla-bla-bla'
...
Рейтинг: 0 / 0
При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
    #38919571
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard93Но ведь вторая часть условия не должна выполняться, например выражение w (0 && $classname(123)) выведет 0 т.к. это short-circuit AND.Так она и не выполняется, но зато выполняется$$$ERROR($$$FormalArgTypeInvalid, $classname(val) ,"Setstream()","%Stream.TmpCharacter")
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / При присвоении объекта в свойство класса копируется сам объект, а не ссылка на него?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]