Code Monkey home page Code Monkey logo

classes.jl's Introduction

Build Status Build status codecov Coverage Status

Classes.jl

A simple, Julian approach to inheritance of structure and methods.

Motivation

Julia is not an object-oriented language in the traditional sense in that there is no inheritance of structure. If multiple types need to share structure, you have several options:

  1. Write out the common fields manually.
  2. Write a macro that emits the common fields. This is better than the manual approach since it creates a single point of modification.
  3. Use composition instead of inheritance: create a new type that holds the common fields and include an instance of this in each of the structs that needs the common fields.
  4. Use an existing package that provides the required features.

All of these have downsides:

  • As suggested above, writing out the duplicate fields manually creates maintenance challenges since you no longer have a single point of modification.
  • Using a macro to emit the common fields solves this problem, but there's still no convient way to identify the relatedness of the structs that contain these common fields.
  • Composition -- the typically recommended julian approach -- generally involves creating functions to delegate from the outer type to the inner type. This can become tedious if you have multiple levels of nesting. Of course you can write forwarding macros to handle this, but this also becomes repetitive.
  • Neither of the packages I reviewed -- OOPMacro.jl and ConcreteAbstractions.jl -- combine the power and simplicity I was after, and neither has been updated in years.

Classes.jl provides one macro, @class, which is a simple wrapper around existing Julia syntax. Classes.jl exploits the type Julia system to provide inheritance of methods while enabling shared structure without duplicative code.

The @class macro

A "class" is a concrete type with a defined relationship to a hierarchy of automatically generated abstract types. The @class macro saves the field definitions for each class so that subclasses receive all their parent's fields in addition to those defined locally. Inner constructors are passed through unchanged.

Classes.jl constructs a "shadow" abstract type hierarchy to represent the relationships among the defined classes. For each class Foo, the abstract type AbstractFoo is defined, where AbstractFoo is a subtype of the abstract type associated with the superclass of Foo.

Given these two class definitions (note that Class is defined in Classes.jl):

using Classes

@class Foo <: Class begin       # or, equivalently, @class Foo begin ... end
   foo::Int
end

@class mutable Bar <: Foo begin
    bar::Int
end

The following julia code is emitted:

abstract type AbstractFoo <: AbstractClass end

struct Foo{} <: AbstractFoo
    x::Int

    function Foo(x::Int)
        new(x)
    end

    function Foo(self::T, x::Int) where T <: AbstractFoo
        self.x = x
        self
    end
end

abstract type AbstractBar <: AbstractFoo end

mutable struct Bar{} <: AbstractBar
    x::Int
    bar::Int

    function Bar(x::Int, bar::Int)
        new(x, bar)
    end

    function Bar(self::T, x::Int, bar::Int) where T <: AbstractBar
        self.x = x
        self.bar = bar
        self
    end
end

Note that the second emitted constructor is parameterized such that it can be called on the class's subclasses to set fields defined by the class. Of course, this is callable only on a mutable struct.

In addition, introspection functions are emitted that relate these:

Classes.superclass(::Type{Bar}) = Foo

Classes.issubclass(::Type{Bar}, ::Type{Foo}) = true
# And so on, up the type hierarchy

Adding the mutable keyword after @class results in a mutable struct, but this feature is not inherited by subclasses; it must be specified (if desired) for each subclass. Classes.jl offers no special handling of mutability: it is the user's responsibility to ensure that combinations of mutable and immutable classes and related methods make sense.

Defining methods to operate on a class hierarchy

To define a function that operates on a class and its subclasses, specify the associated abstract type rather than the class name in the method signature.

For example, give the class Bar, you can write a function that applies to Bar and its subclasses by specifying the type AbstractBar:

my_method(obj::AbstractBar, other, stuff) = do_something(obj, other, args)

See the online documentation for further details.

classes.jl's People

Contributors

carlolucibello avatar davidanthoff avatar rjplevin avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.