Class内のObjectをDestructできない

下記検証ソースはaMain/ClsA/ClsBの3Moduleから構成されています
ClsAはClsBをSetでき、ClsA.ValでClsB.Valを呼び出しできます。

ClsA内にSetしたClsBのObjectを、ClsA.ObjNothigやClsA.Class_Terminate
で Nothingしてますが。
その後、ClsBを生成した側(aMain)で、ClsBの状態を確認すると
Nothingされてないと判定されます([02][03][04])。(想定外:通常のMain-Subの
関係だとNothingされている[05])
※まるでClsA内にあるClsBへの参照のみ解除しているような振る舞い

言語仕様なのでしょうか?
すいません適当なDocに辿り着けておらず,できれば
この挙動について言及されているサイトを教えて
もらえると助かります。

検証環境は 7.4.7.2(x64)です。

【以下検証ソースです】

----[Module:aMain]----
Option Explicit
Option Base 0
Option Compatible

Private Sub aMain
CompatibilityMode(True)
Dim wClsA as Object : wClsA = new_ClsA()
Dim wClsB as Object : wClsB = new_ClsB()
Set wClsA.Obj = wClsB
Msgbox “[00]ClsA.Val:” & wClsA.Val
wClsB.Val = 22222222
Msgbox “[01]ClsA.Val:” & wClsA.Val
Dim wStr as String
wClsA.ObjNothing
wStr = “[02]ClsA.ObjNothing : ClsA/ClsB”
wStr = wStr & vbCR & “ClsA[” & IIF( wClsA Is Nothing, “Nothing”, “Exist”)
wStr = wStr & vbCR & “ClsB[” & IIF( wClsB Is Nothing, “Nothing”, “Exist”)
MsgBox wStr
Msgbox “[03]ClsB.Val:” & wClsB.Val
Set wClsA = Nothing
wStr = “[04]ClsA = Nothing : ClsA/ClsB”
wStr = wStr & vbCR & “ClsA[” & IIF( wClsA Is Nothing, “Nothing”, “Exist”)
wStr = wStr & vbCR & “ClsB[” & IIF( wClsB Is Nothing, “Nothing”, “Exist”)
MsgBox wStr
Call aSub( wClsB)
wStr = “[05]Call aSub : ClsA/ClsB”
wStr = wStr & vbCR & “ClsA[” & IIF( wClsA Is Nothing, “Nothing”, “Exist”)
wStr = wStr & vbCR & “ClsB[” & IIF( wClsB Is Nothing, “Nothing”, “Exist”)
MsgBox wStr
End Sub

Public Function new_ClsA() as Object
Set new_ClsA = New ClsA
End Function

Public Function new_ClsB() as Object
Set new_ClsB = New ClsB
End Function

Private Sub aSub( aCls as Object)
Set aCls = Nothing
End Sub

----[Module:ClsA]----
Option Explicit
Option Base 0
Option Compatible
Option ClassModule

Private mObj as Object

Private Sub Class_Initialize()
End Sub

Private Sub Class_Terminate()
Set mObj = Nothing
End Sub

Public Property Set Obj ( aObj as Object )
Set mObj = aObj
End Property

Public Function Val() as Long
Val = mObj.Val
End Function

Public Sub ObjNothing()
Set mObj = Nothing
End Sub

----[Module:ClsB]----
Option Explicit
Option Base 0
Option Compatible
Option ClassModule

Private mVal as Long

Private Sub Class_Initialize()
mVal = 77777777
End Sub

Private Sub Class_Terminate()
End Sub

Public Property Let Val ( aVal as Long )
mVal = aVal
End Property

Public Property Get Val () as Long
Val = mVal
End Property

オブジェクト指向について理解がおいついてない者です。
他の開発言語だとClsA.mObjをNothingにするとClsBもNothingになるということでしょうか。

適当なサイトも探せなかったのですが、参考になるかもしれないサイトを紹介します。
Qiita記事【VBA】値渡しと参照渡しについて調べてみる
T.B.P.日本語版 19.これまで語られなかったまたは 不正確に語られたLibreOffice Basicの基本

sabr0さん

確認ありがとうございます。
>オブジェクト指向について理解がおいついてない者です。
⇒私自身、オブジェクト指向言語/開発環境は聞きかじった程度で、理解不足・誤認
だらけだと思っています、いろいろと教えていただけると助かります。

>他の開発言語だとClsA.mObjをNothingにするとClsBもNothingになると
いうことでしょうか。
⇒Libre Basic(Option ClassModule)の挙動として、想定してます。
aMain内>Set wClsA.Obj = wClsB なる式で、 ClsA.mObjに
ClsBが設定されます。以降のaMain内において
aMain内>wClsA.ObjNothingやaMain内>Set wClsA = Nothingで、
Set ClsA.mObj=Nothingを行っていますので、それらのタイミングで
sabr0さんが確認されている”ClsBのNothing”を行ったつもりなんですが、
ClsBがNothingされると、aMain内のMsg [02]や[04]でのClsBの
状態表示はいずれも(ClsB Is Nothing)=Trueと予想しましたが、
現状はFalseになっています。(想定外)
※ちなみにaMain内>wClsA.ObjNothing直後に wClsA.Valを呼ぶと、
ClsA.mObjはNothingになっているのでエラー「BASICランタイムエラー
オブジェクト変数は設定できれいません」が発生します

>【VBA】値渡しと参照渡しについて調べてみる
⇒コマンドリファレンスでは、省略時は ByRefだったと記憶しています。
今回は、ByVal/ByRef無指定なのでByRefとの認識です
※ClsB等ObjectはByVal指定は無効なんですね
※Variant変数に配列を格納した場合はByValが有効なんですね

一応、比較確認として、aMain内>Call aSub( wClsB) で aSub内でClsBを
Set Nothingしてますが、その後 aMain内の Msg[05]での ClsBの状態表示は
(ClsB Is Nothing)=Trueになっています(想定通り)
※ClsA内で ClsBに対してSet Nothingしているのでなぜ同じ結果に
ならないのでしょうか?

>T.B.P.日本語版 19.これまで語られなかったまたは 不正確に語られた
LibreOffice Basicの基本 1
⇒内”7: Object変数やVariant変数をリセットする方法”が本件に関する
参考箇所かと。当方としても、オブジェクト変数に Set Nothingすると
オブジェクトがリセットされるとの認識です。
当方は、オブジェクト変数に Set Nothingすると 変数に格納されている
Class がDesutructされる(つまり 該当Classに記載されている
Class_Terminateが呼び出される)との認識です。下記参考URL参照
参考URL:https://wiki.documentfoundation.org/images/f/fa/LibOBasic_09_StructDataTypes_Flat_A4_EN_v101.pdf

すいません、当初の掲載の補足も兼ね、長々記載しました。

1 Like

本件、自己解決したので、その経緯を記載します
__ テーマ:ClassObjectをDestructするには
__ 誤 認:そのClassを参照する変数(wObj)をSet wObj = Nothing すればDesturctする
__正しくは:そのClassを参照が全て無くなればSystemが自動でDestructする
でした。

ですから、最初の検証ソースで、wClsB Is Nothing で該当のクラスびDestructの判定を行うこと自体誤り(他の変数から該当のクラスを参照してればDestructされないので)でした。

以下の検証ソースは、その挙動を確認するために準備しました。ClsA/ClsBのConstructor/Destructorが呼びだされた場合は大域変数(gClsA_St,gClsB_St)にその旨を格納する仕組みで、Destructのタイミングを可視化してます。
※wClsA(ClsAの参照を格納) を Set Nothingした時点でClsAはDesturctしてます。しかし wClsB(ClsBの参照を格納) を Set Nothingした時点では、ClsBはDesturctしませんでした。これは ClsBへの残り参照が、関数名(new_Cls)にまだ格納されているためです。その参照は、その後再度関数(new_Cls)呼び出し new_Cls(“Dmy”) した時、関数名が初期化(=ClsBへの参照が解除)された結果、ClsBへの参照が全てなくなり ClsBがDestructされてます。
=======================テストソースのStart
検証環境は 7.4.7.2(x64)です。
■■Module: aTstMain■■
Option Explicit
Option Base 0
Option Compatible

Public gClsA_St as String
Public gClsB_St as String

Private Sub aTstMain
CompatibilityMode(True)
gClsA_St = “-----”
gClsB_St = “-----”
Dim wClsA as Object
Set wClsA = new_Cls(“A”)
Dim wClsB as Object
Set wClsB = new_Cls(“B”)
Print “[01]” ,gClsA_St & " | " & gClsB_St
Set wClsA = Nothing
Print “[02]” ,gClsA_St & " | " & gClsB_St
Set wClsB = Nothing
Print “[03]” ,gClsA_St & " | " & gClsB_St
Set wClsA = new_Cls(“Dmy”)
End Sub

private Function new_Cls( aX as String) as Object
Print “[new_Cls START]” ,gClsA_St & " | " & gClsB_St
Select Case aX
Case “A” : Set new_Cls = New ClsA
Case “B” : Set new_Cls = New ClsB
Case Else : Set new_Cls = Nothing
End Select
End Function

■■Module: ClsA■■
Option Explicit
Option Base 0
Option Compatible
Option ClassModule

Private mObj as Object

Private Sub Class_Initialize()
gClsA_St = “ClsA Initialize”
End Sub

Private Sub Class_Terminate()
gClsA_St = “ClsA Terminate”
Set mObj = Nothing
End Sub

Property Set Obj( aObj as Object )
Set mObj = aObj
End Property

■■Module: ClsB■■
Option Explicit
Option Base 0
Option Compatible
Option ClassModule

Private Sub Class_Initialize()
gClsB_St = “ClsB Initialize”
End Sub

Private Sub Class_Terminate()
gClsB_St = “ClsB Terminate”
End Sub
=======================テストソースのEnd
私自身、『クラスオブジェクトへの参照が全て無くなるとDestructする』知識はあったのですが、それに加えて『クラスオブジェクトへの参照変数を(ひとつでも)Set Nothingすると、Destructする』と誤認していました。・・・(LO RefCard LO Basic StructuredDataType にも Set oMyObject = Nothing
The class destructor is called at that time. って記述されてたので…)

かような誤認に基づき、これまでクラス設計・実装では、もろもろの後処理を、全て Destructorに詰め込んでましたが、思うとおりDestruct(詰め込んだ後処理[特にFileIOのClose終了処理]が起動)せず困ってしまい、この掲示板に問い合わせしたのでした。

正しい認識に基づくとDestructorの起動タイミングは管理しずらいので、今後は後処理用メソッドを準備し、それを適時呼び出す考えに改めます。

尚、参考にしたサイトは以下です(VBAに関する記述ですが…)
参考URL:VBA Set Obj = Nothing は必要か - t-hom’s diary

私の誤認の問い合わせで、皆さんの貴重な時間の浪費となりすいませんでした。

【PS】これまで掲載内容は、TextEditorで一旦編集し、この掲示板掲載内容編集画面に貼り付けで掲載してますが、行のTabや先頭空白が無視されたりして、皆さんの掲載より体裁が貧弱で 恐縮してます。たぶん、掲載内容編集画面の上にあるいくつかのアイコン等を駆使すれば、前述の不満に加えインデントや図形・表等の貼り付けができるのでしょうが、使い方が分かっていません。このアイコンの使い方や何か掲載内容の体裁を整えるテクニックが記載されたサイトを教えていただけると嬉しいです。
-以上-

2 Likes

エディタの、PreFormattedTextで行けると予想します。
試しに書いてみますね

あああ
あああ	あああ
	Tab
		TabTab

hidemuneさん
この掲示板編集画面上部にある”</>”アイコンをおすと、変種画面に表示される”type or paste code here”の部分をつぶして記載すればいいのですね。
以下が該当のアイコンを押して生成されたPreFormattedText領域のようです。
(領域の前後行に”・・・”がついている。表示画面には表示されなてないから制御情報かしら)
先頭の空白や、複数の改行を実際入力してみます

ここからPreFormattedText領域
  先頭の空白(全角)入れました
       先頭の空白(半角)いれました


複数の改行入れました
ここまでPreFormattedText領域

さてこれでReplyしてみます

期待通り、先頭空白や複数改行をひょうげんすることができました。
ありがとう。

2 Likes

このサイトの利用方法の説明は

英語サイトでピン留されている上位3項目を参考にしてください

ちなみに、このサイトの利用方法等についての質問場所は

また、このサイトのプラットフォーム Discourse についての質問は

特にマクロに関する質問の最も簡単なテクニックはサンプルファイルを添付することです

2 Likes

nobuさん

本投稿内容の体裁について、関連情報の掲載場所連携いただきありがとうございます。

掲載内容の体裁について

LibreOffice Ask環境がDiscourseなるアプリケーションとは…初耳でした。
そのDiscourseの関連情報を連携いただき、感謝します。

初心者の私としては、チュートリアルが、機能の動作確認をしながらが覚えることでき分かりやすかったです。
(リファレンスも用意されていて、親切です)

当方、チュートリアルを体験し、いままでより見やすい体裁で掲載できそうです。

LibreOffice Ask掲示板の使い方について

nobuさん記載の

英語サイトでピン留されている上位3項目を参考にしてください

ですが、LibreOffice Ask掲示板の上段にある絞り込みプルダウンで
English+all tags+all を指定した際、表示されるタイトルの内、押しピンアイコンとともに掲載される、下記タイトル

This is the guide - How to use the Ask site?

の掲載情報が nobuさんの誘導先に該当しますよね、これから読み込みます(当方 英語がダメダメなので時間がかかると思いますが、がんばります)。

ところで、nobuさんの記載 ”~上位3項目を参考にしてください”とは、どこが該当しますかね、前述の掲載情報は一通り読むつもりですが、ほかの掲載情報が該当するなら指摘願います。

ともあれ、nobuさんhidemuneさんらのおかげで、今までよりよみやすく掲載できそうです。ありがとうございました。

1 Like