GithubHelp home page GithubHelp logo

Comments (6)

trusktr avatar trusktr commented on June 2, 2024 1

After thinking about #14 (and not liking the implementation, though I like the outer API), I think what I'm going to do is try an onion-like approach like what you've got (instead of branching), except that I want to be able to pass vanilla classes (not parameterized class factories) into the multiple() (or mix().with()) call.

If possible, what I'd to do is take the vanilla classes passed as input, then build internal class factories that accept parameterized superclasses, then use those class-factories internally in the implementation so that the end user does have to even know about the class-factory pattern.

So, the idea is this, if possible:

class Foo {}
class Bar extends Foo {}
(new Bar) instanceof Foo // true

let Klass = multiple(Foo) // take note!
class Baz extends Klass {}
(new Baz) instanceof Klass // true
(new Baz) instanceof Foo // true (is this possible?)

class Lorem {}
let Clazz = multiple(Foo, Lorem) // take note!
class Ipsum extends Clazz {}
(new Ipsum) instanceof Clazz // true
(new Ipsum) instanceof Foo // true (is this possible?)
(new Ipsum) instanceof Lorem // true (is this possible?)

This way (if possible) plain vanilla classes remain vanilla classes that don't have to be used with any extra patterns, so the end class designer does not need to use a mixin pattern (class factories), and needs not make any API calls when extending a single class (unlike currently, where a class-factory requires an API call even if extending from only a single mixin class). For example, if I just want to extend Lorem from above, I only need to use plain ES6 class syntax:

class Something extends Lorem {}

I would not have to do any of the following just to extend a single class:

class Something extends Lorem(class {}) {}
class Something extends mix(class {}).with(Lorem) {}
class Something extends multiple(Lorem) {}

So, basically,

// import ES6 classes
import Foo from './Foo'
import Lorem from './Lorem'

// --- extend one class:
class Something extends Lorem {}

// --- extend more than one class:
class Something extends mix(Foo).with(Lorem) {}
// or
class Something extends multiple(Foo, Lorem) {}

// --- instanceof:
(new Something) instanceof Lorem // true in all cases

Alright, I'm going to go try and implement it...

from mixwith.js.

machineghost avatar machineghost commented on June 2, 2024 1

Can I suggest that you put this workaround:

class ClassWithMixinButNoParent extends Mixin(Object);

somewhere in the documentation for mixwith (or in the excellent blog post which spawned it ... or both)?

I think it's an essential pattern for a significant percentage of people who want to use mix-ins (not every class has a parent), and it'd be nice if others didn't have to dig through the issues to find it.

P.S. Thanks for pioneering this technique; IMHO it should be the one true pattern for doing mix-ins in JS.

from mixwith.js.

trusktr avatar trusktr commented on June 2, 2024

See #14 for a technique that allows to pass plain classes (instead of mixins). Interesting to note though that we can pass mix().with() classes to the multiple call in #14.

from mixwith.js.

trusktr avatar trusktr commented on June 2, 2024

Crap, well, the following doesn't work, which makes me think it might not be possible to make implement it, because super won't work:

    function A() {
        console.log('A')
    }
    A.prototype.constructor = A
    A.prototype.hello = function() {
        return 'hello'
    }

    function B() {
        console.log('B')
        super() // VM chokes, Error, super not expected here.
    }
    B.prototype = Object.create(A.prototype)
    B.prototype.constructor = B
    B.prototype.hello = function() {
        return super.hello() + 'there' // VM chokes, Error, super not expected here.
    }

    new B

I wish super would work like that.

Well, let me actually give the implementation a shot...

from mixwith.js.

justinfagnani avatar justinfagnani commented on June 2, 2024

Subclass factories necessarily need to parameterize the superclass, so it can't work with plain classes.

One workaround is to define both a mixin and trivial application of it to Object:

const Thingable = (superclass) => class extends superclass { ... }
class ThingableBase = Thingable(Object);

class MyThing extends ThingableBase { ... }

from mixwith.js.

trusktr avatar trusktr commented on June 2, 2024

Here's my implementation of a Mixin helper, which returns a plain class.

Usage is like this:

import Mixin from 'lowclass/Mixin'

const Foo = Mixin(Base => class Foo extends Base { /* ... */ })

// extend Foo directly:
class Bar extends Foo { /* ... */ }

// or if you have en existing class:
class Lorem extends Ipsum { /* ... */ }

// mix Foo functionality into it:
class Lorem extends Foo.mixin( Ipsum ) { /* ... */ }

Thanks Justin for initial inspiration. 😊

One workaround is to define both a mixin and trivial application of it to Object:

That's what my Mixin does there, returning the default application, and saving the mixin on the .mixin static prop of the returned class.

from mixwith.js.

Related Issues (20)

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.