無差別に技術をついばむ鳥

情報処理技術全般を気まぐれにつつくゆるいブログです

VB.NETを咥えてWindows.Formsをつつく4−継承1。親の仕様を無視するな!逃走ボタン。

前回はオブジェクト指向の目玉である継承をつついたピヨ♪だけどまだつつきたりないから今回も継承をつつくピヨ♪ということで、早速サンプルコードをご覧あれ!


Imports System
Imports System.Text
Imports System.Drawing
Imports System.Windows.Forms

Public Class FormProgram
    Public Shared Sub Main()
        Dim frm As PiyoForm = Nothing
        For i As Integer = 0 To 100
            'ピヨフォームを用意するピヨ♪
            frm = New PiyoForm(i)
            frm.Show()
            '逃げるボタンを追加♪
            Dim btn As EscapingButton = New EscapingButton()
            frm.Controls.Add(btn)
        Next
        frm.BackColor = Color.Red
        Application.Run(frm)
    End Sub
End Class


Imports System.Drawing
Imports System.Windows.Forms

'逃走ボタン
Public Class EscapingButton
    Inherits Button

    Private rand As Random

    Sub New()
        rand = New Random()
        Me.Text = "私をクリックしないで!"
        Me.Width = Me.CreateGraphics().MeasureString(Me.Text &  _ 
                           "あ", Me.Font).ToSize().Width
    End Sub

    Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
        MyBase.OnClick(e)
        'クリックされたら消える
        MessageBox.Show("ぐはあっ!やられた・・・")
        Me.Dispose()
    End Sub

    Protected Overrides Sub OnMouseHover(ByVal e As System.EventArgs)
        MyBase.OnMouseHover(e)

        'クリックされないように逃げる
        Dim x As Integer = rand.Next(0, Me.Width + 100)
        Dim y As Integer = rand.Next(0, Me.Height + 100)
        Me.Location = New Point(x, y)

        '画面上をはみ出た場合戻る
        If Not Me.Parent Is Nothing Then
            Dim flag As Boolean = False
            If x >= Me.Parent.Width Then
                x = rand.Next(0, Me.Parent.Width)
                flag = True
            End If
            If y >= Me.Parent.Height Then
                y = rand.Next(0, Me.Parent.Height)
                flag = True
            End If
            If flag = True Then
                Me.Location = New Point(x, y)
            End If
        End If

    End Sub

End Class


こんな具合に継承を禁止されていないクラスは何でも継承できるピヨ。じゃあ、このサンプルコードを動かそう!あっ!丁度いい時に人が来た。ドリィちゃんちょっとこれ見て♪
ドリィちゃん「何この悪趣味な画面?!それに何かしらこのボタン・・・そんなこと言われたらクリックしたくなるじゃないのぉ。えぃ!あっ逃げられたぁ!こしゃくなぁぁーえぃっ!えいっ!えいっ!よしやったわよ!あれ?何でボタンなのにクリックしたら消えるの?」
ボクオリジナルの逃走ボタンだからさ♪
ドリィちゃん「???あのねぇ。ボタンはクリックされるためにあるんだから、このボタン意味ないわよ!」
が〜ん!
ドリィちゃん「ばかぁ。もうまた変なものつくてぇ。まぁ、面白いけどね(ぼそ)論理的整合性をコンパイラはチェックしてくれないから、みんな注意してね❤親クラスの仕様をじっくり調べて、注意して子クラスを実装してね❤」
今回の教訓:子クラスを実装する時、親クラスの役割をよく考えて論理的整合性が崩れないようにしよう。
※適切な表現にするために記事を修正しました。
別窓 | Windows Form | コメント:8 | トラックバック:0 | ∧top | under∨
<<ネタつつき32ープログラミングとシステム構築 | 無差別に技術をついばむ鳥 | VB.NETを咥えてWindows.Formsをつつく3−継承。ピヨ伝染♪>>

この記事のコメント

...どこが矛盾した継承なのかわからんです。
矛盾しているのはボタンの機能じゃなくて?
2009-03-15 Sun 18:08 | URL | επιστημη #-[ 内容変更]
επιστημηさん、コメント有難うございます。
お察しの通り、矛盾した部分はボタンの機能です。
それで矛盾した継承と書いている理由は、この逃走ボタンがボタンから派生しているのも関わらず、本来ボタンが果たすべき役割を放棄しているからです。
クリックしたら駄目なボタンはボタンとはいえませんよね?
この記事では、「継承とは論理的整合性」も自動的に継承されるものではないので注意して欲しいと考えて書きました。
こんな露骨なケースは殆どありませんが、よく考えたら矛盾しているクラスが実務でたびたび見かけますので、初心者が犯しやすい過ちなのかもしれないと私は考えたのです。
2009-03-15 Sun 18:45 | URL | インドリ #-[ 内容変更]
うーん...違う気がする。
「論理的整合性」は自動的に継承されているのに、
メソッドを「わざわざ再定義」して整合性を壊してるんじゃないかな。
2009-03-15 Sun 22:06 | URL | επιστημη #-[ 内容変更]
なるほど、確かに余計な事をしているだけですね。
この間違いを正確に表すには「破壊的継承」と表現した方がよろしいでしょうか?
2009-03-16 Mon 09:10 | URL | インドリ #-[ 内容変更]
いや、この設計/実装に誤りは見られない。
思った通りに作ってるし、作った通りに動いてる。
矛盾があるとあすれば、ドリィちゃんと指摘通り、
「押せるべきボタンを押せなくする」という要求/仕様そのものにあるんじゃないかしら。
2009-03-16 Mon 19:57 | URL | επιστημη #-[ 内容変更]
επιστημηさんコメント有難うございます。
大変参考になります。
よりよい記事を書くために御聞きしたいのですが、こういった「要求/仕様のミス」の注意を促すにはどのように書けば読者に伝わると思いますか?
是非アドバイスを頂きたいです。
2009-03-16 Mon 20:32 | URL | インドリ #-[ 内容変更]
「注意しましょう」以外に返す言葉が見つかりません。
2009-03-16 Mon 23:02 | URL | επιστημη #-[ 内容変更]
επιστημη さん返信有難うございます。
了解しました♪
2009-03-17 Tue 07:25 | URL | インドリ #-[ 内容変更]
∧top | under∨

コメントの投稿

 

管理者だけに閲覧
 

この記事のトラックバック

∧top | under∨
| 無差別に技術をついばむ鳥 |