質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.13%

vbaでのクラス継承時の定数について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,997

K.T_build

score 26

vbaでの継承について、質問をさせて頂きます。
javaのようにスーパークラスにメンバ変数を設定し、それのアクセスをしたいのですが毎回インターフェースを設定する必要があるのでしょうか?

理想

'スーパークラス:absClass.cls
Option Explicit

'プロパティ
Private WS As Worksheet
Private wsName As String
Private startCol As Integer
Private startRow As Integer

Public Sub calc()
End Sub
'サブクラス:centerToMonth.cls
Option Explicit
Implements absClass

Private Sub Class_Initialize()
    '初期値宣言
    wsName = "営業所別_月間"
    startCol = 3
    startRow = 6
    Set WS = ActiveWorkbook.Worksheets(wsName)
End Sub

Private Sub absClass_calc()
    '計算処理
End Sub

Private sub hoge()
End Sub

現実?

'スーパークラス:absClass.cls
Option Explicit

'プロパティ
'Public WS As Worksheet
'Public wsName As String
'Public startCol As Integer
'Public startRow As Integer
'Public colLen As Integer

'' プロパティのインターフェイスを用意する。
Public Property Get WS() As Worksheet
End Property
Public Property Get wsName() As String
End Property
Public Property Get startCol() As Integer
End Property
Public Property Get startRow() As Integer
End Property

Public Sub calc()
End Sub
'サブクラス:centerToMonth.cls

Option Explicit
Implements absClass

'プロパティ
'【質問点】何故サブクラスで宣言するのでしょうか?
Private WS As Worksheet
Private wsName As String
Private startCol As Integer
Private startRow As Integer

'メンバー設定
Public Property Get absClass_WS() As Worksheet
    Set absClass_WS = WS
End Property
Private Property Get absClass_wsName() As String
    'absClass_wsName = wsName
    absClass_wsName = "営業所別_月間"
End Property
Private Property Get absClass_startCol() As Integer
    absClass_startCol = startCol
End Property
Private Property Get absClass_startRow() As Integer
    absClass_startRow = startRow
End Property


Private Sub Class_Initialize()
    '【質問点】定数を設定する場合はInitializeでするのが一般的でしょうか?
    '         それともgetterでするのがよいのでしょうか?
    '初期値宣言
    wsName = "営業所別_月間"
    startCol = 3
    startRow = 6
    Set WS = ActiveWorkbook.Worksheets(wsName)
End Sub

Private Sub absClass_calc()
    '計算処理
End Sub

Private sub hoge()
End Sub


http://teratail.com/questions/88452[前回の質問の続きです。]


【質問点まとめ】

  1. メンバ変数の宣言は何故サブクラスで行うのでしょうか?
  2. メンバ変数を宣言するのに、毎回インターフェース(setter, getter)を設定する必要があるのでしょうか?

また、よろしければ皆さんならばこうしているという例文などをいただけると非常に助かります。

オブジェクト指向も学習中で突飛な質問かもしれませんがよろしくお願い致します。


【(追記)やりたいこと】

スーパークラス

  1. 単月系シート処理用
  2. 年間系シート処理用

サブクラス

  1. 事業所一覧_月間シート処理(単月系シート処理用を継承)
  2. 事業所別営業一覧_月間シート処理(単月系シート処理用を継承)
  3. 営業別得意先一覧_月間シート処理(単月系シート処理用を継承)
  4. 営業別外注一覧_月間シート処理(単月系シート処理用を継承)
  5. 事業所一覧_年間シート処理(年間系シート処理用を継承)
  6. 事業所別営業一覧_年間シート処理(年間系シート処理用を継承)
  7. 営業別得意先一覧_年間シート処理(年間系シート処理用を継承)
  8. 営業別外注一覧_年間シート処理(年間系シート処理用を継承)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

こんにちは。

そもそも、スーパークラスとサブクラスの関係にするということは、複数のサブクラスを作りたいということだと思いますが、合っていますか?
複数のサブクラスを作成する必要がなければ、単純にクラスだけ作れば良いので。

1.メンバ変数の宣言は何故サブクラスで行うのでしょうか?

⇒継承しているスーパークラスはあくまで抽象クラスとして実体は持っていないから。

2.メンバ変数を宣言するのに、毎回インターフェース(setter, getter)を設定する必要があるのでしょうか?

⇒サブクラスとして固有のものなら不要ですけど、インターフェースとして共通化したいなら必要です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/17 19:10

    現状で言うサブクラスのコンストラクタで共通クラスのインスタンスを生成して、そのクラス内で利用するようなことです。

    キャンセル

  • 2017/08/17 19:27 編集

    BeatStarさんも言われていたコンポジションのことであってますでしょうか?
      ※http://promamo.com/?p=4291

    簡単に書いてみましたがこんなイメージでしょうか?
    /*----------------------------------------------
    ■共通クラス(SuperClass)
    private name As String
    private count As Integer

    /*----------------------------------------------
    ■サブクラス1(sub1)
    private super As SuperClass
    private const startRow As Integer = 1
    private const startCol As Integer = 1

    private sub Class_Initialize()
      super = new SuperClass();
      super.name = "hoge";
      super.count = 1;
    end sub

    private function getName()
      getName = super.name
    end function
    /*----------------------------------------------
    ■サブクラス2(sub2)
    以下略

    キャンセル

  • 2017/08/17 19:58

    そうですね。
    共通でgetter/setterを作らないなら、publicで宣言しないと駄目ですけど、そんな感じです。
    これであれば、定数も共通クラスに定義すればいいですし。(getterは必要ですけど)

    キャンセル

+2

私は趣味でC++でやっています。なので的外れなこと言う可能性がありますが。

変数だけのクラスはインターフェースとは言わないようです。

インターフェースは「こういうメソッドを持っている」っていう定義。

単なる定義です。外部に公開するためのもの。質問者さんは外部の人に「私の家はここにあり、こういう宝石や金になるものを持っています」なんて公開しますか?

「VB インターフェース メリット」で検索すると、

連載! とことん VB: 第 15 回 インターフェイスの使いどころ

がヒットしました。

インターフェースを定義して何が楽しいか。

それは (そのインターフェースを継承していれば ) どのクラスのオブジェクトだろうが そのメソッドを使うことが出来るっていうこと。

例えば ITest っていうインターフェースを継承すれば

Dim test As ITest
test = New Test1("Hello")

ってやると、

test は ITestで定義されているやつは"必ず持っている"のでどのクラスのオブジェクトかを気にせずに使える。

( 必ず実装しないといけないってことは、実装完了していれば 要件を満たしているってことで、持っているってことにもなるため。 )

で、privateな変数は使用者からすればどーでもいい。

必要なのは、そのクラスで何ができるかと、どういうメソッドを持っているかだけ。( 例外がある言語だと例外の有無や例外の種類も。 )

なので インターフェースは 変数を定義できない。

もしできるとしたら、インターフェースじゃなくて 単なるクラス ( 親クラス。 )です。

ということで変数は基本的には 実装クラスで定義。

ですが、単なるクラス ( 名称がわからない... ) として定義し、それを継承するなら フィールドとして定義できます。

その場合は言語によるのかもしれませんが、protected にするか、private フィールド & get/set になると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/17 14:44

    インターフェース = 基礎的な機能の枠組という認識であってますでしょうか?
      ※Animal インターフェースなら、「走る機能」、「吼える機能」、「食べる機能」など

    キャンセル

  • 2017/08/17 14:49

    理想としては、インターフェース ⇒ 親クラス ⇒ 子クラス の流れができればベストかと考えています。
    ただ、親クラスの継承はVBAではできないようです、、、
      http://thom.hateblo.jp/entry/2015/02/09/015135

    キャンセル

  • 2017/08/17 18:27

    私は趣味でやっているので、詳しくはわかりませんが、

    インターフェース = 基本機能の枠組み

    っていう解釈でいいと思います。

    少なくともこういうメソッドは持っているから...っていう。

    親クラスの継承はできない ( on VBA ) ... 初めて知りました。

    一応、ちょこちょこ VBAもやったりしますが、ほとんど ( 今のところ全部か。 ) C言語みたいに関数としてやっているので...

    それなら 親 -> 子 のときはコンポジション ( 包含 ) ではどうでしょうか。

    コンストラクタにあたるやつ ( init か? ) で New で生成して、メンバとして保持するやつ。

    よくデザインパターンで使われている技法です。

    それで、

    Interface -> 親
    Interface -> 子

    で 子は 親をコンポジションするとか。

    ただあまり継承を多用して深くなりすぎると 追いにくいから出来ないってことでは?

    ( 言語的であっても。 それでサポートから除外とか。 )

    キャンセル

+1

A1. 
VBA のスーパークラスには、メンバ関数以外記述できない仕組みなので、変数宣言は記載できないからです。

A2.
提示された、理想の absClass.cls で書かれている「プロパティ」とコメントされているものは、absClass.cls 内でのみ参照可能な「ローカル変数」に該当します。
各クラスで public で変数を宣言すれば「プロパティもどき」はできますが、スーパークラスを用意する意味がなくなってしまいますね。

参考となりそうなホームページを2件示しておきます。
後者はなかなか奥深く、かつ興味深い話でした。

変数の適用範囲
オブジェクト指向と10年戦ってわかったこと

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/17 14:42 編集

    定数を設定するには、サブクラスに private const hoge As ~ みたいな形だけ宣言して、スーパークラス(インターフェース)には何も宣言しない形が一般的になるのでしょうか?

    キャンセル

  • 2017/08/17 16:26 編集

    > 定数を設定するには、サブクラスに private const hoge As ~ みたいな形だけ宣言して、スーパークラス(インターフェース)には何も宣言しない形が一般的になるのでしょうか?

    以下のように、読み取り専用のプロパティのインターフェイスが必要になりそうですね。

    (1) スーパークラスに、public property get hoge ... を宣言。
    (2) サブクラスで private const hoge ... の定数を宣言。
    (3) サブクラスで public property get hoge ... プロパティの実装。

    ※コメントは、md の書式が効かないみたいです。

    キャンセル

  • 2017/08/17 18:23

    なるほど、有難う御座います。
    setterは定義せずにサブクラスでconstするんですね、試してみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.13%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る