Comments (6)
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.
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.
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.
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.
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.
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)
- instanceof check with multiple mixins HOT 1
- setup misunderstanding? HOT 1
- ES3 Implementation HOT 12
- Decorator syntax HOT 1
- Alternative implementation (multiple inheritance with branching prototype chain) HOT 10
- Does mixwith detect and cache sub chains? HOT 1
- New mixin base on existing class HOT 3
- instance instanceof mixin? HOT 4
- Current Version Not In NPM? HOT 4
- Unexpected behavior using rollup
- Compiled version uses ES6 syntax (=>) HOT 21
- Thanks for the inspiration!
- error TS2339: Property 'emit' does not exist on type 'MyClass2'. HOT 1
- TypeError: m is not a function, when extending a class that uses mixins HOT 3
- Extending HTMLElement and Babel
- Update npm package HOT 2
- Error if Symbol not defined. HOT 1
- #feature-request typescript version. HOT 2
- How do i import `mix` (ES6) ? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mixwith.js.