Ruby入門season5~継承~
やっほー。久しぶりの更新です。
今回はクラス継承のお話をまとめます。このエントリをもってRubyはいったんおしまい。
とりあえずいってみよー。
継承により親クラスのインスタンス変数とインスタンスメソッドが引き継がれるのでメソッドを踏襲したい場合やマイナーチェンジをしたい場合に使います。
Rubyの継承はこのように書きます。
require ./(継承したいクラス) class (子クラス) < (親クラス) end
実際に書いてみました。
ペットショップのプログラムです。
親クラス、子クラス、実行メソッドの順に並んでいます。コードテストにかけた結果、
Line 8: syntax error, unexpected tSYMBEG, expecting ')'
def initialize(name:, price:, length:)
^
Line 12: syntax error, unexpected kEND, expecting $end
と返されました。うーーーん。
テストに使ったのは、
codepad
です。
詳しくはこちらを。実際にテストにかけた結果が載っています。
http://codepad.org/vFhqPx8D
class Creature attr_accessor :name attr_accessor :price attr_accessor :length def initialize(name:, price:, length:) self.name = name self.price = price self.length = length end def profile return "#{self.name}は#{self.price}円です。全長は#{self.length}mくらいになります。" end end require "./Creature" #creatureクラスを継承 class Fish < Creature attr_accessor :swim_speed def initialize(name:, price:, length:, swim_speed:) #superを用いてCreatureクラスのinitializeメソッドとの共通項をまとめて継承 super(name: name, price: price, length: length) self.swim_speed = swim_speed end #profileを継承&オーバーライド def profile return "#{self.name}は#{self.price}円です。全長は#{self.length}mくらいです。 泳ぐ速さは#{self.swim_speed}km/hくらいです。" end end require "./Creature" #Creatureクラスを継承 class Reptiles < Creature attr_accessor :run_speed def initialize(name:, price:, length:, run_speed:) #superを用いてCreatureクラスのinitializeメソッドとの共通項をまとめて継承 super(name: name, price: price, length: length:) self.run_speed = run_speed end def profile return "#{self.name}は#{self.price}円です。全長は#{self.length}mくらいです。 走る速さは#{self.run_speed}km/hくらいです。" end end #それぞれのクラスを読み込み require "./Fish" require "./Reptiles" fish1 = Fish.new(name:"バショウカジキ", price:750, length:3.3, swim_speed:112) fish2 = Fish.new(name:"錦鯉", price:40000000, length:30, swim_speed:16) reptile1 = Reptiles.new(name:"バシリスク", price:8000, length:0.6, run_speed:3.6) reptile2 = Reptiles.new(name:"ブラックマンバ", price:50000, length:2, run_speed:16) creatures = [fish1, fish2, reptile1, reptile2] number = 1 creatures.each do |creature| puts "No.#{number} #{creature}" number += 1 end puts "どの生き物が気になりますか?" creature_number = gets.chomp.to_i selected_creature = creatures[creature_number][:name] puts "#{selected_creature}ですね。かわいいですよね。おすすめです。"
修正(2018/09/18)**
順番変えるとエラーは一か所のみになりました。
http://codepad.org/Hv9f5I18
Ruby入門season4~クラス分け~
やっほー。今回はクラスを分けることについてまとめていきます。
コードが増えてくると、一つのクラスに詰め込むのは精神衛生上良くないので、クラスを分けます。
分ける際には、require "./クラス"とします。こうすることでファイル内でファイル外のものを読み込めるようになります。
次に標準入力の受付についてです。ようやく登場しましたね。gets.chompを用いて標準入力を受け付けます。ただしこれは常に文字列として受け付けます。数値として受け付けたいときには、gets.chomp.to_iを使います。これで数値として入力を扱えます。
早速やってみます。これが実行クラス側です。
require "./menu" menu1 = Menu.new(name: "茶碗蒸し", price: 1000) menu2 = Menu.new(name: "釜めし", price: 1200) menu3 = Menu.new(name: "寿司", price: 3000) menu4 = Menu.new(name: "葛餅", price: 600) #配列に入れる。 menus = [menu1, menu2, menu3, menu4] #メニューを表示 index = 0 menus.each do |menu| puts "#{index}. #{menu.order}" index += 1 end puts "ご注文はお決まりですか" order_index = gets.chomp.to_i #注文番号を標準入力から受け取る selected_menu = menus[order_index] #受け付けたメニューを取り出す puts "ご注文は#{order_index}番の#{selected_menu.name}でよろしいでしょうか" puts "おいくつになさいますか" count = gets.chomp.to_i #個数を標準入力から受け取る puts "お会計は#{selected_menu.total_price(count)}円になります"
そしてこれが分割したクラスです。
class Menu attr_accessor :name attr_accessor :price def initialize(name:, price:) self.name = name self.price = price end def order return "#{self.name} #{self.price}円" end def total_price(count) total_price = self.price * count return total_price end end
実行した結果はこんな感じ。
葛餅の気分なので3を選択します。
個数を聞かれます。
個数を入力するとお会計まで計算してくれました。
今回はここまで。
余談ですが、今回からはコードをちゃんと表示できるようになりました。
Ruby入門season3~クラス~
やっほー。今回はクラスに関してまとめます。前回はメソッドをまとめたので自然な流れですね。
基本的な考え方や定義の仕方はJavaと同じです。
中の人の好物である茶碗蒸しでクラスを作りました。
Rubyのクラスはclass / endで定義します。クラス内のインスタンスはattr_accessorで定義します。インスタンスの先頭に「:」が付くので忘れないようにします。
インスタンスの生成は、クラス.newです。Javaによく似ていますね。(Javaはnew クラスでした。)
インスタンスに値を入れるときは、(オブジェクト).(インスタンス)とします。
先ほどのプログラムを実行します。
うまくいきました。
クラスの中でメソッドを定義していきます。
Javaとほとんど変わらないですね。実行してみます。
menu1とmenu2に対してメソッドが確かに呼び出されています。インスタンスに対して呼び出すメソッドをインスタンスメソッドといい、インスタンス変数というものがあります。self.変数とすることで先ほど生成したインスタンスに代入した値をインスタンスメソッド内で呼び出せます。
実行します。
いい感じですね。
ところで、ここまで①クラスを作ってから②インスタンスを生成し、それから③インスタンスに値を入れるという手順でやってきました。Javaでも同じことをしていましたが、Javaには②③をまとめてできるコンストラクタというものがありました。Rubyにも同じ機能はないのでしょうか。
ちゃんとあります。initializeメソッドといいます。実際にコードを見てみましょう。
6行目から9行目にかけてinitializeメソッドが定義されていて、インスタンスの定義と値の代入を同時に行っています。そして、23行目でインスタンスmenu1に対してorderメソッドを呼び出しています。orderメソッドを呼び出したとき、まず実行されるのがinitializeメソッドです。ここでインスタンスとその値を受け取り、それをorderメソッドに渡しています、実行結果を見てみましょう。
うまく出ました。orderメソッドの結果は一行目に出ている通りです。
とはいえ、これではinitializeメソッドで値を代入しているので、呼び出す度にいつも同じ値が呼び出されてしまいます。そこで、initializeメソッドに引数を渡すことで様々な値に対応できるようにしましょう。
5行目から9行目までのinitializeメソッドではインスタンス変数に引数を渡しています。
その引数は23行目でキーワード引数を用いて具体的な値を代入されています。ここの値を変えれば、キーワード引数に紐づいているメソッドの出力は全て変更できます。
さて実行結果を見てみます。
うまくいきました。お土産高っ…
Ruby入門season2~メソッド~
やっほー。今回はメソッドのお話。
以前、Javaのオブジェクト指向の件でも書きましたが、Rubyはオブジェクト指向型言語です。なのでメソッドがあります。
メソッドの定義の仕方は簡単です。def と end でやりたい処理を挟むだけ。
実行します。
うるさい客ですね...とまあこんな感じでメソッドは作れます。
引数も当然増やせます。その際、メソッドを呼び出して引数に代入する際には、メソッドの定義順に代入しなければならないことに注意です。
ちなみにこの例はJavaでいうところのpublic voidに当たるメソッドです。では戻り値を返すメソッドはないのでしょうか。...あります!returnを使います。いつもと全く同じです。
4割引きのセールタイムのメソッドです。実行します。
いい感じですね。今回はメソッド内で0.6、つまり小数を乗じているので、結果も小数型で出力されています。なので、600円が600.0円という為替の表記のようになっています。
戻り値には真偽値も取れます。その場合にはメソッド名の直後に?をつけます。
某電機量販店と被っていますが一切関係ありません。地域最安値でなければ割引に応じてくれ、地域最安値であれば割引を拒まれるメソッドです。実行します。
キレられなくてよかった...price = 12000, area_lowest = 9000なので割引に応じてくれました。メソッドの中でifを使えばさらに細かい処理もできるようになりますね。
最後にキーワード引数に関してです。引数が増えると、呼び出す際にどの引数を書いているのか、順番を気にしないといけないので確認するのが面倒です。そこでキーワード引数です。前回のシンボルの件と同じです。
実行します。
...ブルジョワですね。ホストクラブメソッドです。引数を代入するところで「:」を使っています。このように書くと、どの引数に何を代入するのかを明確化できていいですよね。
今回はここまで。
Ruby入門season1~演算記号・条件分岐・配列・キャッシュ~
やっほー。
今回はRubyのお話。
入門of入門のお話をまとめます。
標準出力はputs "(出力内容)"です。JavaでいえばSystem.out.println, C++でいえばcoutに当たるものですね。
四則演算については他の言語と同じです。
変数に関しては型を宣言する必要はなく、いきなり書いていいみたいです。驚き。
そして出力中に変数を入れたいときには#{変数}として出力する文字列や数値に含めてよいです。これを変数展開といいます。C++やJavaでは、(文字列) + 変数 + (文字列)としてきたので、Rubyの柔軟性はいいですね。数値と文字列を出力で連結することはできないので、この記法で型が異なっても出力できるようにあらかじめ埋め込んでいると考えれば自然かもしれませんね。
条件分岐に関しては、ifで始まりendで終わります。endはこれまでの言語では出てこなかったので、忘れないようにしないとですね。条件分岐で、分岐が3つ以上あるときには、if/elsif/else/endの順で記述します。elifでもelseifでもなく、""elsif""です。スペルに気を付けましょう。
次に配列です。配列も配列を宣言することなく、(変数) = [値1、値2、…]のように書きます。配列中の特定値を取り出すときは、配列変数[インデックス番号]とします。変数展開も可能です。
C++やJavaと大きく異なるのは繰り返し文です。Rubyではeach文を使います。
配列.each do |変数名| / endで書きます。このときの変数名は好きなものをつけられます。繰り返しは要素数分だけ行われます。
配列の次はキャッシュです。キャッシュは値を「キー」と結びつけます。表記の仕方は{キー => 値1, キー => 値2,...}です。複数種類のキーを使って値を記述すれば、代入先の変数を一気に記述できます。例えば、こんな感じ。
これでsushi変数にマグロの情報を代入できました。これをputs sushiとすると、出力は「{"name" => "まぐろ", "price" => "130円", "wasabi" => "あり"}」となります。
ハッシュでは、変数[キー]とすることで特定のキーの値のみ取り出すことも可能です。そして、特定のキーに新たな値を代入することで値の更新が可能です。また、キーを新たに追加することもできます。追加する場合はキャッシュの最後尾に追加されます。
ところで毎回キーに""をつけるのはめんどくさいですよね。そこでキーの頭に「:」をつける書き方もあります。これを「シンボル」といいます。「""」「''」の代用だと今は考えてもらってOKです。正確には異なりますが、いまは気にしなくてOKです。
と、ここまでいろいろ書きましたが、実際には、
と書けます。もっとも値を取得する際にはシンボルを使います。
キャッシュと条件分岐を組み合わせることもできます。
存在しないキーを指定するとnilとなり、条件分岐ではfalseとなります。先ほどのsushiの例からpriceをなくして動かしてみます。
実行するとこうなります。
うまくいきましたね。
キャッシュは配列に組み込むこともできます。
⁂wasaiではなくwasabiです。修正します。<2018/09/07>⁂
実行してみます。
130円なら食べよう...って感じで、えんがわの情報が手に入りました。
えんがわがさび抜きなのか否かだけを知りたいときはどうしたら良いのでしょうか。
簡単です。まずえんがわの情報が入っているキャッシュを取り出してから、キャッシュ内のインデックス番号を指定することで欲しい情報をピンポイントで取り出せます。
⁂priveではなくpriceです。修正します。<2018/09/07>⁂
実行します。
正しく出ました。
each文の中に入れてみました。
実行します。
いい感じですね。ちなみにeach文の変数(| |の中のもの)で変数展開しないとエラーになります。中の人はしばらくそれに気が付かないでエラーを吐かれ続けました。
今回はここまで。
Java入門season8~クラス継承~
やっほー。今回はクラス継承についてまとめます。
これなくしてJavaは語れませんね。
クラス継承をすれば、より抽象的なクラスを作り、そのクラスを継承してカスタマイズするというコードの書き方ができるようになります。つまり、重複を少なくできるということです。
継承されるクラスを「スーパークラス」、継承してカスタマイズしたクラスを「サブクラス」といいます。
表記の仕方は、class (サブクラス) extends (スーパークラス)です。
mainメソッド内での呼び出し方はいつもと同じです。
(クラス名) (インスタンス) = new (クラス名);
(インスタンス).set...で具体的な値をセットできます。
サブクラスでカスタマイズしたいときは、追加したいメソッドを書き足すだけです。
mainで呼び出すときは、(インスタンス).(メソッド)で呼び出します。
と、ここまで基本的なことを書きましたが、一番重要なことは「継承は一方通行」だということです。
スーパークラスからサブクラスへの継承はできても、サブクラスからスーパークラスへの継承はできません。
これを利用してメソッドのオーバーライドを行います。
先ほど、クラス継承をしてカスタマイズ可能であると書きましたが、メソッドのオーバーライドがまさにそのことです。サブクラスでスーパークラスと同名のメソッドを定義するとサブクラス側のメソッドが優先されます。上書きされるということです。そしてスーパークラスのメソッドをサブクラス側で呼び出す場合には、super.メソッド()とします。これでスーパークラス側のメソッドをサブクラス側で呼び出せます。
コンストラクタに関してですが、サブクラスでコンストラクタを定義するときは、まず先頭でスーパークラスのコンストラクタを呼び出さなければならないというルールがあります。super()で呼び出せます。
定義の手順についてですが、スーパークラスでコンストラクタを定義します。次にサブクラス内でコンストラクタを定義します。そしてそのコンストラクタ内でsuper(仮引数)とします。この仮引数がスーパークラスのコンストラクタの仮引数に引き渡されます。
クラス継承で問題になるのはフィールドのアクセス制限です。なんでもかんでもset/getを使うのではなく、protectedを使い手もあります。protectedはクラス内とサブクラスからのみアクセスが許されるものです。privateだとそのクラス内のみアクセス可能でありサブクラスからのアクセスができません。だからといって何でもかんでもpublicを使うのも考えものです。カプセル化の意味もなくなってしまうからです。
クラス継承では各クラスの最大公約数的なメソッドを新たにスーパークラスとして定義し、各クラスはそのスーパークラスを継承して必要に応じてカスタマイズします。ここまではスーパークラス内にあるメソッドは全て具体的な処理内容を伴っていました。しかし、実際にはメソッドは同じでもその処理内容は異なる場合も考えられます。例えば、movementというメソッドがあっても、人間と魚、蛇ではその中身は異なります。
このとき、中身が異なるからといって全てのクラスにmovementというメソッドを書くのは重複になり保守性の低下につながります。そこで、処理内容は書かずにメソッドだけスーパークラスに定義しておく手段が欲しくなります。ここで登場するのが抽象メソッドabstractです。publicの前に書きます。一つでも抽象メソッドがあるクラスは抽象クラスといい、クラス名の前にabstractを付けます。abstractはオーバーライドを強制します。上書きされなければエラーになります。また、抽象クラスからはインスタンスを生成することはできません。
今回はここまで。
マルウェアの種類のお話。
やっほー。以前のエントリで簡単に攻撃の種類が云々と書いた気がしますが、こちらで改めてまとめます。主に攻撃に用いられるもののお話ですかね。
以前のエントリではざっくりofざっくりとしかまとめておかなかったので、今回はその補充を。というか、こちらがまとめで以前の分がその補充というべきなんですけどね。まあいいやその辺は。
ではさっそくいってみよー。
★そもそも…マルウェアって何?
よく聞く言葉ではありますが、マルウェアと聞いて何かをすぐに答えられる人は少ないと思います。ぱっと浮かぶのは「ランサムウェア」ですかね。
マルウェアとは、データをパクったり改ざんしたりコンピュータを乗っ取ったり…といった悪意あるコードの総称です。要はクソ迷惑なコードのこと。
有名なものは次のようなものがあります。
・ボット
・ウイルス
・ワーム
・スケアウェア
・中間者
1.ボット
オンライン上で自動的に動くことを目的に作られています。ボットのほとんどは無害です。Twitterでよく見る自動投稿アカウントは○○botなんて名前の人気コンテンツに関連したものが多いですよね。しかし、ボットネットという悪意のあるものや一見無害そうでも攻撃者の命令があれば動き出すようにプログラムされたボットもあります。
2.ランサムウェア
有名なマルウェア。感染するとユーザのデータなどを暗号化して見られないようし、身代金を要求してくるマルウェア。基本的にはユーザの知らないキーを用いて暗号化しますが、中にはシステムの脆弱性につけこんでデータを暗号化してくるものもあります。ファイルのDLやシステムの脆弱性などから感染する可能性があります。
3.ウイルス
これもよく聞くものですね。ウイルスは他の実行ファイル内に含まれる悪意あるコードで、基本的にはユーザの何らかのアクションを必要とします。メールやUSBなどを通じて拡散されています。
4.トロイの木馬
これも有名ですね。音楽のファイルやゲームなど実行ファイルなどにも含まれ、正当な操作を装い、悪意あるコードを実行します。
5.ワーム
一番の特徴は、自ら増殖できるということでしょうか。ネットワークの脆弱性につけこんで増殖し単独で活動します。拡散する速度も極めて速いです。
6.スパイウェア
名前からして既に悪いですね。名前の通り、ユーザをスパイします。つまり、ユーザのコンピュータの利用状況やキーストロークの収集を行い、セキュリティ設定の変更を行います。セキュリティ設定を変更してそのレベルを下げるので、トロイの木馬など他のマルウェアとセットになっていることがあります。スパイウェアでセキュリティをガバガバにしたのちトロイの木馬などのマルウェアで好き放題やるという流れですね。
7.アドウェア
「アド」は広告のadvertisementのadです。広告配信を行いつつどさくさ紛れにスパイウェアなどを入れてくるマルウェアです。
8.スケアウェア
ポップアップウィンドウからセキュリティ上の問題を伝える(ふりをする)など、危機感につけこんでくるマルウェアです。このポップアップウィンドウに従ってプログラムを実行するとマルウェアに感染します。
9.ルートキット
OSを弄ってくるマルウェア。攻撃者のためにバックドアを設置するので、攻撃者はこれ以降好き放題コンピュータにアクセスできるようになります。権限の昇格などの変更とシステムファイルの変更を行うなど、深刻な問題を引き起こしかねないマルウェアです。
10.中間者
暗号の話をやったことがあれば中間者攻撃(Man-in-the-middle)などを聞いたことがあるかもしれません。それと同じような話で、攻撃者はユーザの情報を受信できるようになります。Mitによりユーザに知られることなくデバイスを操作でき、財務情報を盗聴するために広く使われています。MitMoは攻撃者にユーザの情報を送信させ、SMSなどの2段階認証ですら潜り抜けられます。
今回はここまで。