Inheritance should be understood in terms of properties (and operations on properties) of a classes and sub-classes. In functional programming language, application of functions like *func_1*(x, y, *func_2*(z, p)) is implicitly exploiting the idea of inheritance. Making such relationships explicit in programming languages will lead to much less errors at run time with compile time ( definition and declaration ) checks.
On Friday, October 23, 2015 at 7:59:26 AM UTC-7, Brendan Tracey wrote: > > On Friday, October 23, 2015 at 7:38:37 AM UTC-6, Abe Schneider wrote: >> >> An OO approach is really just specifying an interface in a formal manner. >> The second you write any type of interface, you always risk making a choice >> that will haunt you down the road. I don't see the difference between >> >> class Foo { >> float getX() { ... } >> float getY() { ... } >> } >> >> and: >> >> type Foo { ... } >> function getX(f::Foo) -> float { ... } >> function getY(f::Foo) -> float { ... } >> >> except that an instance of `foo` is being passed implicitly in the first >> case. To that extent, I would say Julia OO (i.e. on the dispatching). Where >> it is not OO is in the layout of the data. >> > > In some languages there is no difference. In Go, a method is exactly a > function that can be called with a special syntax. One can do > > c := mat64.NewDense(5, 5, nil) > c.Mul(a, b) > > or one can do > (*mat64.Dense).Mul(c, a, b) > > There aren't many cases where one would actually want to do the latter, > but it makes the definition of behavior clear. > > I think the difference in Julia would be the interaction with multiple > dispatch. In the former case, it seems like getX would live in its own > namespace (only accessible through the Foo class), while in the latter case > it would add to the many definitions of getX. > > > It is true that with a more OO language, because of its formalism, you run >> the risk of declaring variable types in a parent class that might not be >> correct in the child classes, so some planning is required. However, what >> you gain is better code in the long run. For example, I might have: >> >> abstract Baz >> >> type Foo <: Baz { >> x::Float >> } >> >> type Bar <: Baz { >> x::Float >> } >> >> and an interface: >> >> getX{T <: Baz}(b::T) -> Float = b.x >> >> >> which works fine, except maybe someone else comes along and writes: >> >> type Blob <: Baz { >> myX::Float >> } >> >> Now to fix your interface, you have to write a separate `getX` for >> `Blob`. This might not seem like a big deal, except you might not catch >> this issue until run time (I don't think there is a way a static-checker >> could identify the problem). Imagine a large library or base of code, with >> many people working on the code, and you suddenly are exposed to a large >> number of issues. >> > > This seems more like an issue of compiler vs. no compiler issue than one > with OO vs. multiple dispatch. > > You can do OO without inheritance (or OO like things if your definition of > OO includes inheritance). In Go, one would define > > type GetXer interface { > GetX() float64 > } > > I could then write a function > func SquareX(g GetXer) float64 { > v := g.GetX() > return v * v > } > > Now, any type that has a GetX method can be passed to SquareX. There is no > inheritance necessary to make this happen. > >