In clojure I'd write this, if I actually needed a class for type dispatch or interface implementation for some reason.
(s/defrecord Animal
[name :- String
number-of-legs :- Integer])
(def dog (map->Animal
{:name "dog"
:number-of-legs 4}))
The nice thing is that I could also skip the defrecord if I just want enforcement of the shape of the data by making a similar defschema and then I'd just use plain maps.