> In the Animal/Dog/Cat example, what happens if, in a separate module, if define a Snake class that doesn't have a `talk` method? There are several possibilities, sadly all pretty bad
The abstract class defines which methods every class that inherits from it must define by using abstract methods. If you write a class that inherits from an abstract class, and you do not define a method that the abstract class says that you absolutely must define, the compiler will raise an error for you. You can inherit from classes between modules.
> I'm asking about the errors that the language prevents, not the community's conventions.
I haven't actually tried it, definitely something I'll check out another time. I understand your concern though!
> The abstract class defines which methods every class that inherits from it must define by using abstract methods.
In their example, the type checker can infer that Animal has a `talk` method, even if it's never explicitly defined:
abstract class Animal
# no talk method here!
end
class Dog < Animal
def talk
"Woof!"
end
end
class Cat < Animal
def talk
"Miau"
end
end
class Person
getter pet
def initialize(@name : String, @pet : Animal)
end
end
john = Person.new "John", Dog.new
In their own words, “Now the code compiles:”
john.pet.talk #=> "Woof!"
Now, what happens if, in a separate module, I define a Snake subclass of Animal, without a talk method? What happens in this corner case isn't documented anywhere.
Type system design is very serious business, and can't be done by mindless trial and error. When a type system has a safety hole, patching it is pretty much guaranteed to break other people's code.
I can't seem to reply to your reply to this, but the error message has nothing to do with where a class is defined.
You can't compile a part of your application in crystal, there are no linked crystal libraries. You compile your whole app, will all class definitions. The compiler then will have all the type information to know if a method is missing in a subclass, when that method is used from a parent class.
Well, that's even worse. Whole-program compilation has positive aspects to it, like enabling more aggressive optimizations, but it should be strictly opt-in.
For future reference: The easiest way to reply to a message that doesn't have a “reply” link below, is to click on the “X minutes ago” link above.
The compiler does some incremental compilation for the generated object files, so compile times are kept relatively small. Other than that, I don't think it makes a big difference for a developer except saving compile times. On the other hand, in this way you can't have a compiled library conflict so you have to "clean and rebuild" when this happens.
For example in Ruby there's no such thing as pre-compiling a gem, and every time you run an app the whole app is "analyzed" (parsed and converted to VM instructions), and so you can think in Crystal it's the same (except that it's compiled to native code)
Incremental compilation isn't a good alternative to actually separate compilation. If I implement a module Foo that depends on another module Bar, the only information I need is the interface Bar exposes, so I shouldn't have to wait until Bar is actually implemented to begin implementing Foo.
It will simply stop compiling the code and it will say "undefined method 'talk' for Snake". You will get a similar error if `talk` is defined as an abstract method in the base abstract class. So abstract methods are just a standard way to document this and to improve error messages. There's no safety hole here.
The abstract class defines which methods every class that inherits from it must define by using abstract methods. If you write a class that inherits from an abstract class, and you do not define a method that the abstract class says that you absolutely must define, the compiler will raise an error for you. You can inherit from classes between modules.
> I'm asking about the errors that the language prevents, not the community's conventions.
I haven't actually tried it, definitely something I'll check out another time. I understand your concern though!