By Guillaume Briday
Different type of types.
// src/main/java/io/core/person/Person.java
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
}
}
# person.rb
class Person
def initialize (name, age)
@name = name
@age = age
end
end
person = new Person("Alice", 30)
class Dog {
public function speak() {
return "whoaf";
}
}
class Cat {
...
}
function speak(Dog $animal): void {
echo $animal->speak();
}
speak(new Dog); β
//=> "whoaf"
speak(new Cat); β Uncaught TypeError: speak(): Argument #1 ($animal) must be of type Dog, Cat given.
class Dog {
speak () {
return 'whoaf'
}
}
const Cat = {
speak () {
return 'miaou'
}
}
function speak (animal: Dog) {
console.log(animal.speak())
}
speak(new Dog) β
//=> "whoaf"
speak(Cat) β
//=> "miaou"
"If it walks like a duck, and it quacks like a duck, then it must be a duck"
Duck typing is about defining objects by what they do instead of who they are.
class Trip
def prepare(preparers)
preparers.each do |preparer|
case preparer
when Mechanic then preparer.prepare_bicycles(bicycles)
when TripCoordinator then preparer.buy_food(customers)
when Driver
preparer.gas_up(vehicle)
preparer.fill_water_tank(vehicle)
end
end
end
end
class Mechanic
def prepare_bicycles(bicycles)
#...
end
end
class TripCoordinator
def buy_food(customers)
# ...
end
end
class Driver
def gas_up(vehicle)
#...
end
def fill_water_tank(vehicle)
#...
end
end
class Trip
def prepare(preparers)
preparers.each do |preparer|
preparer.prepare_trip(self)
end
end
end
# when every preparer is a Duck that responds to βprepare_tripβ
class Mechanic
def prepare_trip(trip)
prepare_bicycles(trip.bicycles)
end
end
class TripCoordinator
def prepare_trip(trip)
buy_food(trip.customers)
end
end
class Driver
def prepare_trip(trip)
gas_up(trip.vehicle)
fill_water_tank(trip.vehicle)
end
end
Enforce it with modules
module Preparer
def prepare_trip(trip)
raise "Not implemented"
end
end
class Trip
def prepare(preparers)
preparers.each do |preparer|
preparer.prepare_trip(self)
end
end
end
class Mechanic
include Preparer
end
class TripCoordinator
include Preparer
end
class Driver
include Preparer
end
def import_state_badge(import)
variant = {
enqueued: :secondary,
processing: :info,
error: :danger,
completed: :success
}[import.state.to_sym]
badge_tag(value: import.state.titleize, variant: variant)
end
<%= import_state_badge(@import) %>
<%= import_state_badge(@budget) %>
<%= import_state_badge("completed") %>
.d.ts
files for Ruby.
# working_day_calculator.rb
require 'date'
class WorkingDayCalculator
attr_accessor :period_start, :period_end
attr_reader :days_off
def initialize
@days_off = []
end
def add_day_off(date)
@days_off << date
end
def calculate_working_days
((period_start..period_end).to_a - days_off).length
end
end
# working_day_calculator.rbs
class WorkingDayCalculator
attr_accessor period_start: Date
attr_accessor period_end: Date
attr_reader days_off: Array[Date]
def initialize: -> void
def add_day_off: (Date date) -> Array[Date]
def calculate_working_days: -> untyped
end
# Type checking files:
....................................................................................F
working_day_calculator_test.rb:13:17: [error] Cannot pass a value of type `::String` as an argument of type `::Date`
β ::String <: ::Date
β ::Object <: ::Date
β ::BasicObject <: ::Date
β
β Diagnostic ID: Ruby::ArgumentTypeMismatch
β
β calc.add_day_off('BOOM')
~~~~~~~~~~
Detected 1 problem from 1 file
https://github.com/soutaro/rbs-inline
# rbs_inline: enabled
class Person
attr_reader :name #: String
attr_reader :addresses #: Array[String]
# @rbs name: String
# @rbs addresses: Array[String]
# @rbs return: void
def initialize(name:, addresses:)
@name = name
@addresses = addresses
end
def to_s #: String
"Person(name = #{name}, addresses = #{addresses.join(", ")})"
end
# @rbs &block: (String) -> void
def each_address(&block) #:: void
addresses.each(&block)
end
end