abstract(抽象)クラス
みなさんこんにちは🌚
朝は空気が澄んでいてとてもランニングしやすいです。起きるのは大変ですがちょっと早起きして外にくりだしてみると案外気持ちいいですよ笑
さて今回はのちにやるインターフェースというものに似ている抽象クラスについてまとめます。
抽象クラスについて
今までは基本クラスである程度設計図を作り、派生クラスで少し変更を加える形ばかりを取っていましたが、基本クラスでなんの具体的なデータも入れずとりあえずの雛形だけ作って、派生クラスでその実装を行いたい場合も出てきます。そんな時は基本クラス内でabstractキーワードを使うことで抽象メソッドを作ることができます。そして抽象メソッドを含むクラスを抽象クラスと言います。
抽象クラスと抽象メソッドの例)
abstract class クラス名
{
abstract 返すデータ型 メソッド名(パラメータリスト);
}
ちなみに派生クラスではこの抽象メソッドの中身を全て実装する必要があります。
長い文を書いてしまいましたが、要点は3〜11行目で、設けた抽象クラスを実装し、3つの数の最大公約数を求めるクラスを作ってみました。だいぶ無駄が多いプログラムだと思うのでどなたかご指摘お願いいたします😅😅今回はここまでにしておきます
この先にやるインターフェースという概念にとても似ているこの抽象クラス。これらの違いについても明確にして行こうと思います🙂🙃
クラスの多層階層とコンストラクタの継承
みなさんこんにちは🌚
FF15を振り返るとやっぱりグラフィックや音楽・演出などが素晴らしいです。モチーフとなったベネツィアの写真を見ると思ってたよりオルティシエでした笑
いつか死ぬ前に一度は訪れてみたいです
さて今回はクラスの多層階層についてまとめていこうと思います。その名の通り多層に渡って継承をするのですがここまで継承をわかっている人ならなんとなくどんな感じになるか察しているんじゃないかなとも思います🙄
多層階層について
基本クラスから派生させた派生クラスを基本クラスとして、さらに派生させることもできます。
Bruno039クラスで各基本クラスと派生クラスのインスタンスを生成しています。最初のb1 = b2 の代入は予想通りshowクラスがオーバーライドされています。次のb1 = b3の代入はいきなり基本クラスに派生の派生であるBruno039クラスのインスタンスを代入していますが結果はみてわかるようにちゃんと間のBruno038クラスも継承されています。では次に、コンストラクタを景初した場合の処理についてまとめます。
コンストラクタの継承について
コンストラクタはクラスと同じ名前を持つメソッドのことを指し、そのクラスの中で一番最初に実行され主にそのクラスの初期化に使われるものでしたね。このコンストラクタは先ほどのように継承されるとどうなるのでしょうか
継承されるたびにその派生クラスのコンストラクタが呼び出されていることが確認できますね。今回は少し短いですがここまでにします。
急に朝が寒くなったような気がします。もう半袖の人は全然見かけません。ゲーム製作に取り付ける日は来るのだろうか....
オーバーライドについて
みなさんこんにちは🌚
講義が忙しすぎて試合とバイトとトリプルブッキングでつらたんのブルーノです。「天使にラブソングを」をみたのですが最高でしたね。洋画のノリは大好きです笑。シスター見習いのシスター・メアリー・ロバート役のWendy Makkenaがとても可愛いですね。
さて今回はオーバーライドという言葉についてです。とってもかっこいい響きで以前やったオーバーロードに通じるものがありますがオーバーロードとは別物です。
オーバーライドについて
前回やった継承は基本クラスのメソッドの内容に新たに加えるだけでなく、すでにある内容を書き換えることもできます。これにより、一つのメソッドから複数のバージョンのメソッドを作ることができます。これをオーバーライドと言います。ロックマンエグゼで例えるならバリアブルソードみたいなものです。一つの同じチップで様々なタイプの攻撃ができるようになるみたいなものです。さて、オーバーライドされる元のメソッドを仮想メソッド(virtual method)と言い、オーバーライドされた後のメソッドをオーバーライドメソッド(override method)と言います。オーバーライドメソッドを組む上では以下のような細かいルールがあります。
- アクセス修飾子は同じでなければならない
- シグニチャは同じでなければならない
- 静的メソッドはオーバーライドできない
言われてみればまあそうかと思うかもしれませんが結構忘れやすいので注意しましょう。
さてオーバーライドの方法ですがいたって簡単で、基本クラスのメソッドにvirtualキーワードをつけておき、派生クラスで同じ名前のメソッドの前にoverrideキーワードをつけるだけです。
例)
class Base
{
public virtual void Main()
{ ... }
}
class Derived : Base
{
public override void Main()
{ ... }
}
今までやってきたノリならば簡単ですね。しかしここで一つの疑問が浮かびます。前回やった「名前の隠蔽」です。同じ名前にすれば基本クラスのメソッドは無視されるというこのルールがある上でオーバーライドとの違いはなんなのでしょうか。ここからが少し理解が難しいところです。
下の画像をみてください
名前の隠蔽を使ったTaroクラスとオーバーライドを使ったMateクラスで検証を行いました。検証の順番が少々ごっちゃですが許してください😂
1つ目の画像がそれぞれの継承について、2つ目が様々な方法で定義した各クラスの継承、3つ目がその結果についてです。主に2つ目の画像をみていただきたいのですがまずp1とp2インスタンスは名前の隠蔽を用いて普通に通常の方法で継承しているので、結果は予想通りです。注目すべきは3つ目と5つ目で、右辺で宣言した変数の型と左辺で生成したインスタンスの参照の型が違っています。結果はどうでしょうか。名前の隠蔽のPersonクラスの方は基本クラスのままの文章を返すのに対し、オーバーライドしたPeopleクラスは継承されたmateクラスの文章を返しています。これはつまり、名前の隠蔽による継承は「コンパイル時に参照する変数の値に応じてメソッドが決定される」のに対し、オーバーライドは「実行時に生成されたオブジェクトの型によりメソッドが決定される」ことを表しています。前者は動かない入れ物である変数により決定するので静的な型によるものとされ、後者は実行時に決定されるため動的メソッドディスパッチと呼ばれます。
”箱”である参照変数ではなく生成したオブジェクトの型通りにメソッドが動くのはオブジェクトの特徴によって振る舞いが決定するということであり、これがオブジェクト指向プログラミングの重要な要素の一つ「多態性」というものです。いちいち変数でなく自分が定義したメソッド通りに実行されて欲しいのは当然で、こういった時のためにオーバーライドは便利です。
プロパティやインデクサのオーバーロード
メソッドだけでなく、プロパティやインデクサもオーバーライドすることができます。
例)
・プロパティ
class Base
{
public virtual string Prop
{ get, set; }
}
class Derived : Base
{
public override string Prop
{ get, set; }
}
・インデクサ
class Base
{
public virtual string this[string index]
{ get, set; }
}
class Derived : Base
{
public virtual string this[string index]
{ get, set; }
}
具体的にプログラムを組むとこんな感じです
プロパティ
無属性のロングソードのデータを入れたBruno029クラスから派生させたBruno030クラス(火属性)とBruno031クラス(氷属性)をそれぞれオーバーライドさせています。なおどちらの属性のソードもソード系統であるのは変わらないのでKeitouクラスはconstキーワードで変更できないようにしています。ロックマンエグゼでは各属性ソードチップにはお世話になりました
インデクサ
オーバーライドさせたインデクサの方は偶数個めのインデクサにのみ入れることができるので奇数は弾かれます。今回はここまでにしておきます
オーバーライドを使うことですでにあるクラスを様々なタイプに使い分けることができ、とても便利になります。ずいぶん時間がかかりましたがこの記事をまとめている間とても有意義で楽しかったです。
継承の基本、下準備について
みなさんこんにちは🌚
欲しいPS4ソフトが多過ぎて後期の単位が不安なブルーノです。ようやくPS4の時代がきました。金がなくなってゆく....
さて今回は継承の基本についてやっていきたいと思います。
継承について
C#の非常に重要な概念であるクラスの中でもとても重要な要素である継承。その名の通りその性質を引き継ぐことができる機能のことです。どういうことか、まずは下の画像を見てみましょう
まず、3行めから10行めはBruno026クラスですがこれは基本クラス(Base Class)と言います。そしてすぐ下の12から19行めのBruno027クラスの名前の横に「 : Bruno026」とありますがこれはBruno026から派生したということを表し、このBruno027クラスを派生クラス(Derived Class)と言います。そしてBruno028クラスではこれらのクラスをインスタンス化し色々と実験しています。まず25行めで派生クラスであるBruno027クラスをインスタンス化していますが、26,28行めでわかるように基本クラスであるBruno026クラスの中身を用いています。つまり、派生クラスは基本クラスのpublicなメンバを全て引き継ぐことができるのです。privateなクラスは呼び出せないので注意してください。そしてもう一つ注意するのが30,31,32行めでわかるように基本クラスはたとえその前に派生クラスが作られてもなくなったり、変わったりするわけではないということです。
先ほど派生クラスはprivateを引き継げないと言いましたが、では基本クラスの引き継ぐ要素はすべてpublicにすればいいのかというとそれも少し問題があり、publicメンバはその他のクラスからも影響を受ける場合があるのです。この場合は、protectedアクセス修飾子を使います。protected修飾子を頭につけたメンバは、派生クラスからはアクセスできますが、他のクラスからはアクセスできなくなります。なので、メンバを安全にしつつ、派生クラスを作りたい場合はこのprotected修飾子を使いましょう。
では最後に名前の隠蔽について説明しておきます。またかっこいい名前の用語が出てきました。基本クラスと派生クラスに同じ名前のメンバを持たせたい時、派生クラスの方のメンバにnewキーワードをつけることで、同じ名前のメンバを持つことができます。このメンバを呼び出した時、基本クラスのメンバは無視されます。これを名前の隠蔽と言います。逆に無視された基本メンバを呼び出したい時は、baseキーワードをつけて呼び出します
では今回の大まかなまとめをします。今回の結果をまとめると
- クラスの横に「 : 」をつけることでその基本クラスの要素を引き継いだ派生クラスを持つことができる
- 派生クラスを作っても基本クラスはなくならない
- private修飾子を用いると派生クラスからも見えなくなるので派生クラスから見えつつ他のクラスからは見えないようにしたい場合はprotected修飾子を使う
- newキーワードを頭につけることで基本クラスのと同じ名前のメンバを持つことができる。その場合基本クラスの同じ名前のメンバは隠蔽され、それを呼び出したい時はbaseキーワードを使う
この4つですね。次回からは、もっと別の要素についてもまとめていきたいと思います。ここから少しずつ複雑になっていくので、ゆっくり噛み締めながら勉強していきたいです。
来年あたりは新しいPS4のゲームがたくさん出るようでとても楽しみです!!でも最近のソニーのゲームはみんなで一緒にいてわいわいできるものが全然ない気がします( ´Д`)y━・~~
オンラインで化け物みたいな数同時通信できるものが増えるのは嬉しいですがやっぱり一緒にやりたいです笑
インデクサについて
みなさんこんにちは🌚
家のWi-Fiの調子が良くないのでせっかく無料体験中なのにネットで映画がうまく見れないブルーノです。ルーターはレンタルから自分のものに変えたはずなんですが.....
さて今回はインデクサについてです。インデクサは、使い方がプロパティに似ており、インスタンスを配列のように扱うことができるものです。
インデクサについて
インデクサは、次のように定義します。
配列の要素の型 this[インデックスの型 インデックス]
{
get {};
set {};
}
前回やったプロパティと同じ方法ですね。インデックスとは、単純に訳すなら英語で「索引」のことで、ようは目次みたいなものですね。収納するものの番号がこれに当てはまります。プロパティと同じように、getとsetアクセッサを使うことで配列のそれぞれのインデックスにアクセスすることができます。では、単純な例を下に貼ります。
ちゃんとセットした値全てを表示できましたね。配列には5つ要素がありますが、何も入れない場合も反映されるか見るために4つしか入れていません。普通に実行されるようですね。
一つ気になったことがありこのプログラムのBruno024クラスに配列を2つ入れるとどうなるのか、getやsetアクセッサにある配列の名にアクセスするのかなとも思いましたがそれだと少しスマートじゃない気もしました。アクセスするとスローもなく永遠に進まなくなるだけで、強制終了する時の警告文は「mono32が実行中ですが中止しますか?」でした。これを解決するために、インデクサの数も増やしたり、thisの部分を配列名に変えてみましたが、前者はthisが二つあり実行不可、後者はthisキーワードを用いていないので不可という結果になりました。特に後者はインデクサを使用する際の配列の指定はthisじゃなければならないということでとても興味深かったです。もしどなたかこれらについてわかる方がいらっしゃいましたらぜひ教えていただきたいです。
さて今回はここまでにしておきます。ここに書いたこと以上にこの要素は奥が深く、今後重要になってくるはずですので、よく理解を深めておきます。
時間というものは本当に一瞬で過ぎていきます。気を抜いたらあっという間に1日が終わっていて、何度も同じ繰り返しのように見えて、絶対に戻ってきているわけではないし、確実に終わりは訪れるものです。子供の頃は時間が経つのが遅く感じていましたが、今思うとあの頃はあらゆるものに対して自分の中で絶え間なく考察を繰り返していたからかなと思います。知っていくことが増えていく中で諦めや妥協は身に付けたくないですね。子供の頃見てたデジモンフロンティアのWith the Willという歌で同じことを言っていました。なんだか明日からまた頑張れそうです😄
プロパティについて
みなさんこんにちは🌚
友達がみんなこの夏休みに外国とか実家とか行ってるのに一人だけ相変わらず残ってテニスとプログラミングざんまいのブルーノです!LINEポイント欲しさにU-NEXTの一ヶ月体験を登録したら思いの外楽しいです😆でも勉強もしていきましょう!
さて今回はプロパティについてです。プロパティという言葉ならパソコンを使っている時にたまに目にする人もいるんじゃないでしょうか。それと関係があるのか今日は調べていきたいと思います。
プロパティについて
プロパティは、変数に値を入れる時に制限を設けられるシステムです。これはどういうことかというと、例えば身長や体重などの値を入力してもらいたい時、ここに負の値を入れられては困りますよね?そういう時にこのプロパティを使うことで簡単に制限することができます。ifキーワードを使ってもできますが長いメソッドを書く必要があります。プロパティの例としては
データ型 プロパティ名
{
get
{
return xxx;
}
set
{
xxx = value;
}
}
といった感じです。このgetとsetがそれぞれ取得する際と収納する際に用いられるアクセッサというものです。このアクセッサはどうやら最初から決められている一つのメソッドのようです。value; とありますが意味の通り値であり、プロパティに入れる値はここに収まります。なおポイントとしては、プロパティは値を格納するものではないということです。あくまでフィルターのような役割を果たすだけなので、上に xxx とあるように収納する変数は事前に宣言しておきましょう。では例として、昔作ったBMIを測るプログラムに負の値を入れられないよう、このプロパティを使ってみましょう
こんな感じですね。64行めと72行めにあるようにBruno023クラスのメインメソッドで用意した身長と体重の値をそれぞれblpropメソッドとbwpropメソッドに入れています。この時の値が0以下なら弾かれるというわけですね。
では今回はここまでにします。{}の数が多くて一見複雑なように見えますがよく見ると大したことはないですね。もっとこの中身が増えていけば複雑なプログラムになるんだろうなと思います。
すっかり夏の暑さもいなくなり日の出る時間も短くなって行ったように感じます。今年も今年もまた冬が始まりますね。それはまだ早いか🤧
槇原敬之さんの「冬がはじまるよ」いいですよね!マッキーはほんと名曲ばっかりです。