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

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

ただいまの
回答率

90.62%

  • C#

    6834questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C# Windows Formを多重継承したい

解決済

回答 5

投稿

  • 評価
  • クリップ 0
  • VIEW 773

piglet

score 37

こんにちは
現在、コードの保守性を上げる作業をしています。

例えばForm1とForm2で同じ機能のメソッドをいくつか持っている場合
これを共通化して一本にまとめたいのですが良い方法はないでしょうか?

共通のメソッドをまとめてクラス化し、Form1とForm2に継承させれば
綺麗に実装できるのでは?
と思ったのですがC#のFormは既にSystem.Windows.Formを
継承しているためできませんでした。

次善の方法として、Form1とForm2に同じ名前のサブクラスを作り
そいつに共通メソッドまとめたクラスを継承させればいいかなと思ったのですが
メソッドを呼び出す時に、頭にサブクラスの名前が付くのが何となく気持ち悪いです。
例: this.method() → subClass.method() 

どのようにするのが最善なのでしょうか?

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 5

+5

System.Windows.Formを継承している親クラスを作って、そのclassをForm1とForm2に継承させれば良いのでは?

継承元

using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class baseForm : Form
    {
    //作りたい処理
    }
}

継承先

namespace WindowsFormsApplication1
{
    /// <summary>
    /// テスト用フォームです
    /// </summary>
    public partial class Form1 : baseForm //こんな感じで
    {
      …

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/13 17:18

    これかな と思ったんですが
    よく見ると共通する処理が、Form1と「Form2に張り付けてあるUserControl内」にありました
    一体どうすればいいんでしょう(´・ω・`)

    キャンセル

  • 2017/09/13 17:37

    とすると、Formを継承するのはおかしいですね。別クラスにメソッドを切り出すのが良いと思いますが。

    キャンセル

  • 2017/09/14 10:00

    共通のUserControlのみBaseFormに張り付ければ良いのでは

    キャンセル

+2

こんにちは。

System.Windows.Forms.Form <- MyProject.Form
MyProject.Form <- MyProject.Form1
MyProject.Form <- MyProject.Form2


でいいのでは?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/13 14:36

    すいません。 "<-" これの意味がわかりませんでした(´・ω・`)
    継承関係を示すのでしょうか?

    キャンセル

  • 2017/09/13 14:42

    そうです、わかりづらい書き方をしてしまいました……
    motuoさんの回答が同じことを丁寧に説明しているのでそちらを参考にするのが良いと思います。

    キャンセル

+2

例えばForm1とForm2で同じ機能のメソッドをいくつか持っている場合これを共通化して一本にまとめたいのですが良い方法はないでしょうか? 

意味が理解できません。

Visual Studio の「新しい項目の追加」で「Windows フォーム」を選択して追加していくと、Form を継承したクラスが Form1, Form2 ... と自動生成されていきますが、質問者さんの言う「Form1とForm2」はそのことを言っているのですよね?

で、Form1 と Form2 を多重継承して、たとえば Form3 を作りたいが、C# では多重継承ができないので困っていると言ってます?

多重継承する目的が分からないのですが、できないものは何ともならないので、普通に Form を継承した Form3 を作って、それに Form1 と Form2 にあるメソッドを重複しないよう自力でコードを書いて実装するという方法ではダメなのですか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/13 14:33

    質問が悪かったみたいです(´・ω・`)

    Form1とForm2を作ったのですが、結果的に同じ処理をするメソッド(複数)を両者に作ってしまっていた
    同じコードを二ヵ所に書くと後々両方を修正する必要があるので、一ヵ所にまとめたい
    だけど、別のクラスに纏めた場合、どうやってForm1とForm2から呼び出せばいいのだろう
      → これらのメソッドを集めたクラスを継承させれば綺麗に実装できるのでは → 駄目だった
    じゃぁ、ユーティリティクラス(staticな共通の処理のメソッドを集めたクラス)でどうだろう
      → なにか違う。オブジェクト指向的なもっといい方法はないのだろうか? ←いまここ
    こんな感じです。

    キャンセル

  • 2017/09/13 16:34

    以下のような感じ(あくまで感じ、例です)なのでしょうか?

    (1) DB にアクセスしてデータを表示・編集する Windows Forms アプリを作っている。

    (2) UI として Form1 と Form2 を作った。

    (3) DB にアクセスしてデータを取得したり編集したりするコードを Form1 と From2 の両方に実装した。

    (4) 完成した Form1 と Form2 のコードを眺めてみると同じ操作をしているコードが実装されている。

    (5) それらを一か所にまとめたい。

    であれば、プレゼンテーション層(UI を提供する Form)、ビジネスロジック層(From と DB をつなぐ)、データベース層の 3 層構造にし、上記 (3) のコードをビジネスロジック層に実装するというのが普通のやり方だと思います。

    質問者さんのアプリがどういうものか分かりませんが、DB を扱うものではなくても、上に述べたような構造にはできるのではないでしょうか?

    キャンセル

  • 2017/09/13 16:39

    上の私のコメントの、DB にアクセスしてデータを表示・編集する 3 層構造のアプリの具体例を紹介しておきます。

    Windows Forms アプリの場合は、ビジネスロジック層には Visual Studio のデータソース構成ウィザードを利用して型付 DataSet + TableAdapter を作って使うのがよく行われる方法です。

    具体的には、DB が SQL Server の場合ですが、以下のチュートリアル、

    チュートリアル : データベースへのデータの保存 (単一テーブル)
    https://msdn.microsoft.com/ja-jp/library/0f92s97z(v=vs.120).aspx

    10 行でズバリ !! 非接続型のデータ アクセス (ADO.NET) (C#)
    https://code.msdn.microsoft.com/windowsdesktop/10-ADONET-C-cbfe7688

    ・・・のように Visual Studio のデータソース構成ウィザードを利用して型付 DataSet + TableAdapter を作って、それを利用してアプリを作ると、以下のページの図のような構造のアプリが、ほとんど自分でコードを書くこと無しに作れます。

    Windows フォーム アプリケーションでのデータへの接続
    https://msdn.microsoft.com/ja-jp/library/wxt2cwcc(v=vs.120).aspx

    キャンセル

  • 2017/09/14 04:26 編集

    質問の意図が伝わってよかったです。
    作っているのはDBとは違うのですが、フォーム+コントロール+データアクセスという構造は同じです
    なので今後も考えると三層アーキテクチャはありかもしれませんね

    キャンセル

  • 2017/09/14 09:58

    お互い何か勘違いがないでしょうか?

    あるクラスの機能・メソッドを使うにはそのクラスを継承しないと使えないような実装になっている(メソッドに protected 修飾子が付いているとか)という話ではないですよね。

    単に何らかの機能を実現するメソッドをまとめて共通に使いたいという話なら、ozawk さんが言われるように「別のクラスに括ってそいつにお願いする」ということを考えればいいはずです。

    例えば文字列を操作したい場合、String クラスに実装されているメソッド等を探して、使えるものがあればそれを使いますよね?

    質問者さんが独自に必要な機能を実装したクラスライブラリを作れば同じことができるのでは?

    キャンセル

+2

それは多重継承じゃなくても
Formを継承したFormAをさらにForm1,2がそれぞれ継承すればいいです。

System.Windows.Form
<|-- FormA
<|-- Form1 (,Form2)

ですが、「内部で同じようなコードが出てくるからまとめたい」という動機だったら、
継承より移譲のほうがいいと思います。

外部で同じようなコードが出てくる:
Form1のインスタンスもForm2のインスタンスも
FormA型として扱いたい場合がある、
つまり、FormA型の変数に入れたりメソッドの引数にしたい場合だったら、継承のほうがいいです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/14 04:35

    デリゲートですね
    なんかピーンと来たんですが具体的な処理が思いつきませんでした(´・ω・`)
    ちょっと調べてみます。もし良い参考例とか文献がありましたら教えてくださると助かります。

    キャンセル

  • 2017/09/14 07:20

    ここで言う移譲は言語機能のdelegateじゃなくて
    別のクラスに括ってそいつにお願いするって事です

    キャンセル

check解決した方法

0

データを習得するクラスを継承して
重複していた操作メソッドで拡張することでとりあえずは上手くできました。
結果的に、フォーム → コントロール(操作)→ データの操作 という手順になり
一応は、MVCの三層アーキテクチャになったみたいです

VとCが1クラスになっちゃってますが・・・

*追記
まだ勉強不足で理解が足りないみたいなんでオブジェクト指向とかソフトウェア工学あたりを勉強してみます。
回答してくださった皆さんありがとうございました。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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

  • C#

    6834questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。