class A < B
,<
就是继承,A继承B
。
Ruby是单向继承,抱歉我用比较粗俗的方式说明,只可以有一个爸爸,但可以有很多小孩。
另外模组不是养父,是爸爸学会了,儿子就会了,模组也不是越多功能越好,能做到几个相同性质组一个模组最好。还有昨天说明过了,类别方法都会被继承。
继承看code就能明白。设定一个类别。
class Protype_monster
attr_accessor :name, :power
def initialize(name = "黑龙", power = rand(800..900))
@name = name
@power = power
end
def final_fight
final_boss
end
protected
def cant_sleep
puts "有睡眠抵抗力"
end
private
def final_boss
puts "我通常在最後一张地图出现"
end
end
2.7.3 :022 > millaboreus = Protype_monster.new
=> #<Protype_monster:0x00007f88f941b020 @name="黑龙", @power=889>
2.7.3 :023 > p millaboreus
#<Protype_monster:0x00007f88f941b020 @name="黑龙", @power=889>
=> #<Protype_monster:0x00007f88f941b020 @name="黑龙", @power=889>
2.7.3 :024 > millaboreus.final_fight
我通常在最後一张地图出现
=> nil
millaboreus.cant_sleep #NoMethodError:protected方法不能外篰直接使用。
millaboreus.fly #NoMethodError
millaboreus.environment #NoMethodError
再来是一个子层。
class Elder_dragon < Protype_monster
def fly
puts "滞空#{rand(30..50)}秒"
end
def environment
rand(1..10) > 5 ? (puts "改变环境") : (puts "环境未改变")
end
def resistance
self.cant_sleep
end
end
ksardaora = Elder_dragon.new("钢龙")
2.7.3 :042 > p ksardaora
#<Elder_dragon:0x00007f88f9412060 @name="钢龙", @power=850>
=> #<Elder_dragon:0x00007f88f9412060 @name="钢龙", @power=850>
2.7.3 :043 > puts ksardaora.name
钢龙
2.7.3 :044 > puts "力量#{ksardaora.power}"
力量850
##子层没设定的,但父层有,所以继承沿用,attr_accessor系列,initialize的架构。
2.7.3 :045 > ksardaora.fly
滞空38秒
2.7.3 :046 > ksardaora.environment
环境未改变
#子层的方法,父层无法使用。
ksardaora.final_boss #=>NoMethodError ,private的实体方法不继承。
2.7.3 :048 > ksardaora.resistance ##protected内的可继承,所以使用方式正确就可用。
有睡眠抵抗力
可以被很多子类别继承。
class New_elder_dragon < Elder_dragon
end
class Fly_dragon < Elder_dragon
end
2.7.3 :057 > tigrex = Fly_dragon.new("轰龙", 600)
=> #<Fly_dragon:0x00007f88f93f2e90 @name="轰龙", @power=600>
2.7.3 :058 > tigrex.fly
滞空46秒
2.7.3 :059 > tigrex.environment
环境未改变
最後的类别,爸爸跟爷爷会的自己都会,当然这样不算好设计,最後的怪物变什麽都会。
顺便补充了protected
。
重点在於,单向继承,利用子类别里没有的方法
,Ruby会往父层找的功能(父没有,会继续往模组以及父的上层找),子类别可以加入其他更多功能,也不会觉得过於庞大。如有同名方法,看是父或子类别呼叫,以用自己的优先。
与Class
最大差异在於,模组模组间无法继承,以及无法New
物件,Class
中如果引入模组,其子class
会继承到父层引入的模组,但无法模组继承模组,另外Class
的superclass是Module
。
Mixins
:由於Ruby不支援多重继承,可以以模组来扩充功能,让子类别越来越完整。
无论Ruby
或在Rails
上,Module
通常会集中放置。
module Elder
def environment
rand(1..10) > 5 ? (puts "改变环境") : (puts "环境未改变")
end
end
module Flight_mode
def stay_in_the_air
puts "滞空#{rand(30..50)}秒"
end
end
module Scared
def scared
puts "被闪光弹吓到会站着不动"
end
end
module Brute_wyvern
def run_wild
puts "朝向玩家冲撞"
end
def head_hammer
puts "使用头部攻击"
end
end
我把一些skill
先模组化。
接着重新设计class
。
class Biology
include Scared ##引入模组
attr_accessor :name, :power
def initialize(name = "食草龙", power = 10)
@name = name
@power = power
end
def behavior
eat()
end
private
def eat
puts "吃草!"
end
end
2.7.3 :045 > herbivore = Biology.new
=> #<Biology:0x00007fc9c13318e0 @name="食草龙", @power=10>
2.7.3 :046 > herbivore.behavior
吃草!
=> nil
2.7.3 :047 > herbivore.scared
被闪光弹吓到会站着不动
=> nil
初始的class
设计成只有基本功能。
接着第二个类别。
class Velkhana < Biology
include Elder
include Flight_mode #模组引入
def initialize(name = "冰咒龙", power = 650)
@name = name
@power = power
end
def behavior
eat_snow()
end
private
def eat_snow
puts "吃雪!"
end
end
2.7.3 :066 > velkhana = Velkhana.new
=> #<Velkhana:0x00007fc9c1238c18 @name="冰咒龙", @power=650>
2.7.3 :067 > velkhana.behavior
吃雪!
=> nil
2.7.3 :068 > velkhana.environment
环境未改变
=> nil
2.7.3 :069 > velkhana.stay_in_the_air
滞空43秒
=> nil
2.7.3 :070 > velkhana.scared
被闪光弹吓到会站着不动 ## 引入模组会被继承,所以它也会被吓到
velkhana.run_wild #NoMethodError 模组没引入不能用
velkhana.head_hammer #NoMethodError 模组没引入不能用
Velkhana.stay_in_the_air #NoMethodError (undefined method `stay_in_the_air' for Velkhana:Class), include方式导入模组,都是实体方法,类别都不能用。
第三个类别
class Brute_wyverns < Biology
include Brute_wyvern
def initialize(name = "惶怒恐暴龙", power = 700)
@name = name
@power = power
end
def behavior
boom()
end
private
def boom
puts "黑色的大黄瓜,超烦人!"
end
end
2.7.3 :089 > savagedeviljho = Brute_wyverns.new
=> #<Brute_wyverns:0x00007fc9c132af18 @name="惶怒恐暴龙", @power=700>
2.7.3 :090 > savagedeviljho.scared
被闪光弹吓到会站着不动
=> nil
2.7.3 :091 > savagedeviljho.run_wild
朝向玩家冲撞
=> nil
2.7.3 :092 > savagedeviljho.head_hammer
使用头部攻击
=> nil
savagedeviljho.environment #没引入模组,不会这些
savagedeviljho.stay_in_the_air #没引入模组,不会这些
最後来一个什麽都会的魔王。
class Final_boss < Biology
extend Elder, Flight_mode, Brute_wyvern
end
2.7.3 :097 > Final_boss.run_wild
朝向玩家冲撞
=> nil
2.7.3 :098 > Final_boss.head_hammer
使用头部攻击
=> nil
2.7.3 :099 > Final_boss.environment
改变环境
=> nil
2.7.3 :100 > Final_boss.stay_in_the_air
滞空35秒
顺便以这份code显示了,子与父层如有同名方法,可以自行更改做扩充或改变。
def behavior
boom()
end
code中也展示了extend
与include
的差异。
extend
引入的模组方法成为类别方法。
include
引入的模组方法成为实体方法。
还有一个prepend
下面会说道。
这个不是说引用原则,而是设计上怎麽处理,在设计上难免得同名。
引用才发现同名,请乖乖回头修改...
module One
def One.say_hi #Modlue_name.method_name
puts "你好喔!"
end
end
module Two
def Two.say_hi #Modlue_name.method_name
puts "我今天很好喔!"
end
end
class Hello
extend One
extend Two
def hello
One.say_hi
Two.say_hi
end
end
2.7.3 :060 > Hello.new.hello
你好喔!
我今天很好喔!
=> nil
有点反向思考,但没办法,初期常被问的问题之一。
刚刚我尽量模组写在上面,这个要反过来写。
class Hello
prepend One
def say_hi
"你好喔"
end
end
module One
def say_hi
"先呼叫模组的say_hi,再跑到super,也就是父层执行 " + super
end
end
2.7.3 :125 > Hello.new.say_hi
=> "先呼叫模组的say_hi,再跑到super,也就是父层执行 你好喔"
如果没super
class Hello
prepend One
def say_hi
"你好喔"
end
end
module One
def say_hi
"先呼叫模组的say_hi,没了"
end
end
2.7.3 :166 > Hello.new.say_hi
=> "先呼叫模组的say_hi,没了"
如果是改用extend``include
,就没效果了。
class Hello
extend One
include One
def say_hi
"你好喔"
end
end
module One
def say_hi
"先呼叫模组的say_hi,再跑到super,也就是父层执行 " + super
end
end
2.7.3 :029 > Hello.new.say_hi
=> "你好喔"
2.7.3 :030 > Hello.say_hi
NoMethodError (super: no superclass method `say_hi' for Hello:Class)
简单点想extend``include``prepend
都是能挂载模组,extend
引入的模组方法成为类别方法。
include
引入的模组方法成为实体方法。prepend
能让class
使用super
方法,使模组运算完的资料再到自己的方法里处理。
super
...还记得superclass
吗?
2.7.3 :031 > Array.superclass
=> Object
一开始说明继承的程序码,已经显示super
是不用写入,Ruby也会自动使用的,那就看看指定使用的方式。
class Top
def self.one #已经开始懒得想方法名了,直接用self代表连new都懒了
"hello, "
end
end
class Child < Top
def self.one
super + "Player!"
end
end
2.7.3 :048 > Child.one
=> "hello, Player!"
对,不是模组prepend
才能用super
,super
本身就是一种方法。
class Super_top
def self.one
"OH! "
end
end
class Top < Super_top
def self.one
super + "hello, "
end
end
class Child < Top
def self.one
super + "Player!"
end
end
2.7.3 :018 > Child.one
=> "OH! hello, Player!"
娱乐性质示范~~
再来,带参数使用。
class Top
def math(int)
int * 10
end
end
class Child < Top
def math(int)
super * 10
end
end
2.7.3 :012 > Child.new.math(10)
=> 1000
参数是由子传给父层方法处理。
class Top
def math(int)
int = 5
end
end
class Child < Top
def math(int)
int * super
end
end
2.7.3 :012 > Child.new.math(20)
=> 100
接着是如果不想把参数传给上层
class Top
def math
40
end
end
class Child < Top
def math(int)
int * super()
end
end
2.7.3 :012 > Child.new.math(20)
=> 800
最後是传给block
。
class Top
def say_hello
puts "123"
yield
end
end
class Child < Top
def say_hello
puts "456"
super
end
end
2.7.3 :015 > Child.new.say_hello {puts "789"}
789
123
456
呼...
记得require
自己制作的模组不像Math
,虽然Math
也是模组,但已经成为Ruby的标准函式库了。
可以直接以Module_name.Moudle_method_name
这样呼叫
2.7.3 :002 > Math.sqrt(16)
=> 4.0
而其实还是可以引入,直接让irb的空白物件挂载。
:001 > sqrt(16) #这样不行
NoMethodError (undefined method 'sqrt' for main:Object)
:002 > include Math #这样後就可以了
=> Object
:003 > sqrt(16)
=> 4.0
第八天的leetcode989. Add to Array-Form of Integer
题目连结:https://leetcode.com/problems/add-to-array-form-of-integer/
题目重点:很简单,手续比较多而已。
# @param {Integer[]} num
# @param {Integer} k
# @return {Integer[]}
def add_to_array_form(num, k)
end
puts add_to_array_form([1,2,0,0], 34) #=>[1, 2, 3, 4]
puts add_to_array_form([2,7,4], 181) #=>[4, 5, 5]
puts add_to_array_form([2,1,5], 806) #=>[1, 0, 2, 1]
puts add_to_array_form([9,9,9,9,9,9,9,9,9,9], 1) #=>[1,0,0,0,0,0,0,0,0,0,0]
第一个例子其实就把答案说完了。
[1, 2, 0, 0] #=> 1200
:085 > [1, 2, 0, 0].join.to_i
=> 1200
1200 + 34 # Array.join.to_i + k
1234 #=> [1, 2, 3, 4]
:088 > 1234.to_s
=> "1234"
:090 > "1234".split""
=> ["1", "2", "3", "4"]
:091 > ["1", "2", "3", "4"].map{|num| num.to_i}
=> [1, 2, 3, 4]
整理完
def add_to_array_form(num, k)
(num.join.to_i + k).to_s.split("").map(&:to_i)
end
今天提到的
1.类别继承
2.Module
3.super
方法
4.leetcode989. Add to Array-Form of Integer
明天会解释&``monkey patch
。
Ruby部分就介绍完噜!
头一个礼拜发现篇幅过大,重点容易丢失,之後就都是一个Rails问题跟一题Leetcode了。
<<: @Day8 | C# WixToolset + WPF 帅到不行的安装包 [自订动作]
>>: Day 03:专案01 - 超简单个人履历02 | HTML基本元素
我先说一个故事。我认识的一位建筑师长辈,前些日子新居落成,邀请我们去他新家喝咖啡聊天。这位长辈说,他...
我快要猜到你的密码了。等一下,为什麽是我的生日。 我是谁? 徐老师 开玩笑的。我是陈彦龙 ,主修经济...
vue.js2.0後版本推荐使用axios来完成ajax请求 为Promise-based HTTP...
去年参加 Software Development 类别的铁人赛,主题为PHP 大师之路 - 开源的...
今日目标 基本的数学函式库(向量与阵列) 要多少才够 从另一个角度看,我认为游戏中的从小小的让角色移...