- ガルマ・ザビ
- ベテラン
- 会議室デビュー日: 2007/06/07
- 投稿数: 55
- お住まい・勤務地: ジオン公国
|
投稿日時: 2008-02-22 16:27
mName をプロパティ化し、Get、Setを設ける。
PersonalクラスにIPersonalインターフェースみたいなのを継承させ、
mNameのプロパティのゲッターだけ公開。
Formからは、IPersonalインターフェース経由で触らせる、、、とか。
でも、やっぱり、じゃんぬねっとさんのやり方がいいんですけどね、、。
|
- かずくん
- ぬし
- 会議室デビュー日: 2003/01/08
- 投稿数: 759
- お住まい・勤務地: 太陽系第三惑星
|
投稿日時: 2008-02-22 17:38
引用: |
|
ガルマ・ザビさんの書き込み (2008-02-22 16:27) より:
mName をプロパティ化し、Get、Setを設ける。
PersonalクラスにIPersonalインターフェースみたいなのを継承させ、
mNameのプロパティのゲッターだけ公開。
Formからは、IPersonalインターフェース経由で触らせる、、、とか。
|
これ実験してみましたが、インターフェースでReadonlyのプロパティを宣言した場合、
具象クラスでは、Read/Writeなプロパティにはできないっぽいです。
(Visual Studio 2005 VB)
# 何か設定でもあるのかな?
すなわち
コード: |
|
Public Interface IPerson
Readonly Property Name As String
End Interface
Public Class Person
Inherits IPerson
...
Public Property Name As String
Get ....
Set ....
End Property
End Class
|
上記のコードではコンパイルエラーになりました。
泥臭いですが、
コード: |
|
Public Class Person
Private _Name As String
Public Overloads Sub New()
End Sub
Public Overloads Sub New(ImmutablePerson P)
Me.Name = P.Name
End Sub
Public Property Name As String
Get ....
Set ....
End Property
Public ReadOnly Property Person As ImmutablePerson
Get
Return New ImmutablePerson(Me)
End Get
End Property
End Class
Public Class ImmutablePerson
Private _P As Person
Public Sub New(Byref P As Person)
_P = P
End Sub
Public Property Name As String
Get
Return _P.Name
End Get
End Property
End Class
Dim P As Person = New Person()
P.Name = "AAA" 'セットできる
Dim IP As ImmutablePerson = P.Person
P.Name = "BBB" 'セットできないため、コンパイルエラー
|
上記のようなコードしか思いつきませんでした。ふいんき(←なぜか変換できない)的には一郎さんに近いですね。
Companyクラスでは、リストの宣言を
Private mEmployees As New List(Of Personal)
ではなく
Private mEmployees As New List(Of ImmutablePersonal)
にすれば、他からどころか自身でも変更できなく出来ます。
変更したい場合は
コード: |
|
New Person(ImmutablePersonのインスタンス)
|
のように、新しいインスタンスを作成し、元の値と置き換えると。
|
- まりも
- ベテラン
- 会議室デビュー日: 2006/08/19
- 投稿数: 77
|
投稿日時: 2008-02-22 17:53
似たようなことができるように考えてみましたが。
案1.NameプロパティにPrivateなSetを定義して、CompanyクラスをPersonalクラスの内部クラスにする。
これだとクラスが内部クラスになってしまって、影響が大き過ぎる可能性が高いので、
案2.Companyクラス内にNameに対するアクセサっぽいメソッドを作って、それを利用する。
コード: |
|
Public Sub New()
Dim personal As New Personal()
Console.WriteLine(personal.Name)
SetName(personal, "IT太郎")
mEmployees.Add(personal)
End Sub
Private Sub SetName(ByVal personal As Personal, ByVal name As String)
personal.GetType() _
.GetField("mName", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance) _
.SetValue(personal, name)
End Sub
|
私がやるとしたらこんな感じでしょうか。
インターフェース案のほうがいいようなきもしてきましたが。
|
- くまっち
- 大ベテラン
- 会議室デビュー日: 2008/01/18
- 投稿数: 169
- お住まい・勤務地: 茨城県のどこか。
|
投稿日時: 2008-02-22 18:04
コード: |
|
Interface IPerson
WriteOnly Property Name() As String
End Interface
Public Class Person
Implements IPerson
Private _Name As String
Public ReadOnly Property Name() As String
Get
Return _Name
End Get
End Property
Protected WriteOnly Property Name1() As String Implements IPerson.Name
Set(ByVal value As String)
_Name = value
End Set
End Property
End Class
|
セットするときは
CType(Personインスタンス, IPerson).Name = "お名前"
こんな感じで無理やり隠蔽。
[追加]
上記PersonクラスとIPersonインターフェースをCompanyクラスの内部で定義し
IPersonはProtected。PersonはPublicとすることで
Companyクラス以外からは設定出来ない作りになるかな。
どのみち、インターフェース経由しないと設定できない点は煩わしいですが。
やはり別アセンブ・・・(ぃぇ、なんでもないです。
[ メッセージ編集済み 編集者: くまっち 編集日時 2008-02-22 18:37 ]
|
- ガルマ・ザビ
- ベテラン
- 会議室デビュー日: 2007/06/07
- 投稿数: 55
- お住まい・勤務地: ジオン公国
|
投稿日時: 2008-02-22 18:41
引用: |
|
かずくんさんの書き込み (2008-02-22 17:38) より:
これ実験してみましたが、インターフェースでReadonlyのプロパティを宣言した場合、
具象クラスでは、Read/Writeなプロパティにはできないっぽいです。
(Visual Studio 2005 VB)
# 何か設定でもあるのかな?
|
C#だといけたので、VBもいけるかと思い書き込んでしまったのですが、
自分でもVBで書いてみたところ、コンパイルエラーが出ました。
ご迷惑をおかけしました。
|
- ani
- 常連さん
- 会議室デビュー日: 2007/05/17
- 投稿数: 44
|
投稿日時: 2008-02-22 22:42
みなさま、たくさんのそして親切なレスありがとうございます。
大変感謝いたしております。
(まとめてのお礼になり申し訳ありません。)
あれからいろいろと試しまして、以下のようなコードを書いてみました。
コード: |
|
'個人情報クラス
Public Class Personal
Protected mName As String
Protected mAddress As String
Protected mAge As Integer
Public ReadOnly Property Name() As String
Get
Return Me.mName
End Get
End Property
End Class
'個人情報クラス
Public Class Company
Private Class PersonalInherits : Inherits Personal
Public Property _Name() As String
Get
Return MyBase.mName
End Get
Set(ByVal value As String)
MyBase.mName = value
End Set
End Property
End Class
Private mCompanyName As String
Private mEmployees As New List(Of Personal)
Public Sub New()
Dim personal As New PersonalInherits()
Console.WriteLine(personal.Name)
personal._Name = "IT太郎" 'OK
mEmployees.Add(DirectCast(personal, Personal))
End Sub
End Class
'フォームクラス
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim personal As New Personal()
Console.WriteLine(personal.Name)
'personal.Name = "IT太郎" 'エラー
End Sub
End Class
|
何となく動いているようなのですが、問題は多々あると思います。
(基本的に継承の使い方が間違っているとは思います。)
インターフェースについてまだ理解ができていないため、みなさまにご教示いただいたコードはまだ試していません。
申し訳ありません。
よく理解して試してみたいと思います。
また「読み取り専用」の解釈のご指摘、ありがとうございます。
やりたいことは unibon さんがおっしゃった「操作間違いを防ぐ」ことなのですが、
アセンブリが同じであればクラスを使用する側で注意してもらう方が良さそうですね。
私も本当は別アセンブリにしたいです。。。
|