inheritance support

554 views
Skip to first unread message

Mic

unread,
Apr 8, 2012, 8:56:24 AM4/8/12
to juli...@googlegroups.com
Hello,
is it or will it be possible to do somehow inheritance like in Ruby with classes or like in Go.

Looking at the Go examples it would be nicer to have Ruby classes 

Are there any plans to support inheritance or is it already possible?

Thank you in advance.

Tim Holy

unread,
Apr 8, 2012, 9:27:23 AM4/8/12
to juli...@googlegroups.com
On Sunday, April 08, 2012 07:56:24 am Mic wrote:
> Hello,
> is it or will it be possible to do somehow inheritance like in Ruby with
> classes or like in Go.

The current situation is deliberate, see http://julialang.org/manual/types/,
paragraph 4.

I had no role in designing julia, but to perhaps save the core developers from
having to repeat themselves too often, I'll throw in my 2cents about this
issue. In my own experience, I was initially a bit skeptical, and I still
occasionally find myself thinking "oh, I could solve this better with
inheritance." But so far, each time I've thought it through I've found another
way, for example by putting more of the work for a constructor into a separate
function and having multiple types make use of that function. This type of
thinking reduces some of the negatives of not having inheritance. Furthermore,
I have personally experienced some of the problems associated with
inheritance, and I agree that julia's design avoids those traps. So I, at
least, am content with the current situation.

Best,
--Tim

Stefan Karpinski

unread,
Apr 9, 2012, 8:58:06 AM4/9/12
to juli...@googlegroups.com
This is correct. There are never going to be classes in Julia in the C++/Java style. This is by design. Inheriting structure — i.e. tacking fields onto a composite object type — is rarely of much use and has huge downsides. There are two types of sharing that inheritance is suposed to be useful for: sharing structure and sharing behavior. If you want to share structure, delegation is a much better design than tacking extra fields onto a existing composite type. If you want to share behavior, then a better design is to write generic code to an abstract type (a.k.a. a trait in OO lingo) of which the concrete types are specific implementations. To those ends, we probably need some features to improve delegation support, as well as support for multiple inheritance from abstract types. Class-based OO, however, is definitely never going to happen.

kvan...@ksvanhorn.com

unread,
Apr 9, 2012, 11:03:20 PM4/9/12
to julia-dev
Have you considered something like Haskell's type classes as an
alternative to multiple inheritance?

I am guessing that one of the problems with multiple interface-only
inheritance is that you can create method ambiguities that aren't
detectable when the type is created, because the ambiguity was created
after the type was created. For example, if you define T to be derived
from U and V, someone could later define function f with methods f(U)
and f(V); so which applies to objects of type T? Saying that neither
applies isn't a good solution, as you should be able to call f(x) for
any object belonging to type U or belonging to type V -- otherwise the
types aren't that meaningful.

With something like Haskell classes, this problem doesn't occur. A
type class defines a fixed interface; once it's created, you can't add
any additional functions/methods. You define T to be an instance of
type class C by giving the implementation of the type class interface
with T substituted in for the abstract type variable used in C's
definition. Thus any ambiguities should be detectable when when the
type class is defined or a type class instance is defined.

On Apr 9, 6:58 am, Stefan Karpinski <ste...@karpinski.org> wrote:
> This is correct. There are never going to be classes in Julia in the
> C++/Java style. This is by design. Inheriting structure — i.e. tacking
> fields onto a composite object type — is rarely of much use and has huge
> downsides. There are two types of sharing that inheritance is suposed to be
> useful for: sharing structure and sharing behavior. If you want to share
> structure, delegation<http://en.wikipedia.org/wiki/Delegation_(programming)>is
> a much better design than tacking extra fields onto a existing
> composite
> type. If you want to share behavior, then a better design is to write
> generic code to an abstract type (a.k.a. a
> trait<http://en.wikipedia.org/wiki/Trait_(computer_programming)>in OO

Jeff Bezanson

unread,
Apr 9, 2012, 11:20:40 PM4/9/12
to juli...@googlegroups.com
Method ambiguities are already possible in our system due to multiple
dispatch, and we handle it by printing a useful warning. With multiple
interface inheritance as you describe, the only change is that
ambiguity becomes possible with only a single argument, and we could
print the same warning.
The idea of adding syntax for defining interfaces is too bureaucratic
for our taste. If an interface requires certain methods, our approach
is to define default methods on the abstract (interface) type that
throw errors.

Stefan Karpinski

unread,
Apr 10, 2012, 1:37:56 PM4/10/12
to juli...@googlegroups.com
I'm not entirely against the idea of interfaces, but I think that given Julia's multiple dispatch nature the whole concept would need serious reconsideration. It would be nice to be able to know whether you've implemented all the functionality you're expected to implement for something without having to exercise code that triggers that particular error. On the other hand, when developing some functionality, it's really nice to be able to implement an interface incrementally.

Patrick O'Leary

unread,
Apr 10, 2012, 3:31:52 PM4/10/12
to juli...@googlegroups.com
Perhaps there could be some way to express an assertion that dispatches exist for a certain type for a set of methods?


On Tuesday, April 10, 2012 12:37:56 PM UTC-5, Stefan Karpinski wrote:
I'm not entirely against the idea of interfaces, but I think that given Julia's multiple dispatch nature the whole concept would need serious reconsideration. It would be nice to be able to know whether you've implemented all the functionality you're expected to implement for something without having to exercise code that triggers that particular error. On the other hand, when developing some functionality, it's really nice to be able to implement an interface incrementally.

Patrick O'Leary

unread,
Apr 10, 2012, 4:35:45 PM4/10/12
to juli...@googlegroups.com
Relevantly, Niko Matsakis of the Rust team is also currently wrestling with questions about how interfaces should work:
http://smallcultfollowing.com/babysteps/blog/2012/04/10/declared-vs-duckish-typing/

kvan...@ksvanhorn.com

unread,
Apr 11, 2012, 1:36:00 AM4/11/12
to julia-dev
On Apr 9, 9:20 pm, Jeff Bezanson <jeff.bezan...@gmail.com> wrote:
> Method ambiguities are already possible in our system due to multiple
> dispatch, and we handle it by printing a useful warning.

Then what is the problem with multiple inheritance? My impression has
been that the core team has found it problematic in some way.

> The idea of adding syntax for defining interfaces is too bureaucratic
> for our taste. If an interface requires certain methods, our approach
> is to define default methods on the abstract (interface) type that
> throw errors.

It doesn't have to be new syntax. If Julia had the right reflection
capabilities, presumably you could write a macro that would run any
desired checks. Use of the macro would be optional -- you could do
your incremental development, and then use the macro to check, to the
extent possible, compliance with the expected interface.

There is one other problem I'm still worried about. Suppose a user
defines a method for a function f. Unknown to the user, f is also used
in the standard library, either as an internal implementation detail
or explicitly documented. This breaks some behavior of the standard
library, and suddenly all sorts of strange errors are occurring and
the user has no idea why.

Now that I think about it some more, it seems to me that namespaces
might solve this problem, if they're designed carefully. Someone using
a library would know that they're asking for trouble if they go
defining functions/methods in the library's namespace (except where
the library documentation explicitly states that it's safe.)

Stefan Karpinski

unread,
Apr 11, 2012, 10:08:08 AM4/11/12
to juli...@googlegroups.com
On Wed, Apr 11, 2012 at 1:36 AM, ke...@ksvanhorn.com <kvan...@ksvanhorn.com> wrote:
On Apr 9, 9:20 pm, Jeff Bezanson <jeff.bezan...@gmail.com> wrote:
> Method ambiguities are already possible in our system due to multiple
> dispatch, and we handle it by printing a useful warning.

Then what is the problem with multiple inheritance? My impression has
been that the core team has found it problematic in some way.

None. It's just very tricky to implement. Our type and dispatch systems are already pretty complicated, and with multiple dispatch would become even more so. It's something we want but just haven't gotten the chance to implement.
 
> The idea of adding syntax for defining interfaces is too bureaucratic
> for our taste. If an interface requires certain methods, our approach
> is to define default methods on the abstract (interface) type that
> throw errors.

It doesn't have to be new syntax. If Julia had the right reflection
capabilities, presumably you could write a macro that would run any
desired checks. Use of the macro would be optional -- you could do
your incremental development, and then use the macro to check, to the
extent possible, compliance with the expected interface.

There is one other problem I'm still worried about. Suppose a user
defines a method for a function f. Unknown to the user, f is also used
in the standard library, either as an internal implementation detail
or explicitly documented. This breaks some behavior of the standard
library, and suddenly all sorts of strange errors are occurring and
the user has no idea why.

Now that I think about it some more, it seems to me that namespaces
might solve this problem, if they're designed carefully. Someone using
a library would know that they're asking for trouble if they go
defining functions/methods in the library's namespace (except where
the library documentation explicitly states that it's safe.)

I agree that namespaces would solve this problem. You'd have to explicitly import the function before you could add any methods to it, so there's not much danger of doing it accidentally.

On the subject of multiple inheritance, this is one of the advantages of multiple dispatch with external function objects over single dispatch with methods as bundles of named functions: name clash stops being an issue. If there are modules foo and bar that both have a function named f, writing methods to both is trivial: foo.f(x::MyType) = ... and bar.f(x::MyType) = .... Because foo.f and bar.f are distinct function objects, the name clash is irrelevant.
Reply all
Reply to author
Forward
0 new messages