(jsii-go) override constructor jsiimodule.NewBase_Override()
- Dominant language
- TypeScript
- Stars
- 2.9k
- Forks
- 267
- Avg merge
- 1d 25m
- Merged PRs (30d)
- 14
Description
## :rocket: Feature Request
### Affected Languages
- [ ] `TypeScript` or `Javascript`
- [ ] `Python`
- [ ] `Java`
- [ ] .NET (`C#`, `F#`, ...)
- [X] `Go`
### General Information
* **JSII Version:** 1.26.0 (build 7d76e02), typescript 3.9.9
* **Platform:** linux
* [ ] I may be able to implement this feature request
* [X] This feature might incur a breaking change
### Description
As a exercise of studying jsii generated go package code, here is another take at override constructor. The generated code is nice and easy to read, showing two common parts for basic constructor and override constructor:
//still use Bucket as example:
1. create a jsiiProxy_Bucket object which proxy methods as rpc to JS kernel.
either return proxy as default Bucket or embed it in a customized bucket object.
jsiiProxy_Bucket is the "BaseClass" of all buckets.
2. register the bucket (either default proxy or customized) with jsii runtime/kernel.
For the convenience of customizing/overriding, could we separate the above logic into two functions:
```go
type Bucket interface {
...
}
type jsiiProxy_Bucket struct {
args []interface{}
}
//return proxy as "Base" object
func NewBucketBase(bargs ...interface{}) Bucket {
_init_.Initialize()
return &jsiiProxy_Bucket{args: bargs}
}
//register "b" with runtime/kernel
func Bind(b Bucket) {
//find "base" proxy thru reflection
var proxy *jsiiProxy_Bucket
found := findBaseByReflection(b,"Bucket","jsiiProxy_Bucket", &jsiiProxy_Bucket) [code link](https://gist.github.com/yglcode/a14fb1b54d93b024835d51553608eb32)
if !found {
//cannot work without "base" proxy
panic("cannot find proxy")
}
_jsii_.Create(
FQN,
proxy.args,
b,
)
}
```
custom bucket can be defined more explicitly:
```go
type BucketWithPrefix struct {
Bucket
prefix string
}
func NewBucketWithPrefix(bargs ...args) Bucket {
b := &BucketWithPrefix {
Bucket: NewBucketBase(bargs...),
prefix: "...prefix...",
}
Bind(b)
return b
}
func (bp *BucketWithPrefix) OverrideMethod(...) {...}
...
```
and othe customized bucket structs:
```go
type BucketWithPolicy struct {
Bucket
...
}
```
And these custom buckets can be composed:
```go
type ServiceBucket {
Bucket
...
}
func NewServiceBucket(bargs ...) Bucket {
b := &BucketWithPrefix {
NewBucketBase(...),
"...",
}
b = &BucketWithPolicy {
b,
...
}
b = &ServiceBucket {
b,
...
}
Bind(b)
return b
}
```
And ServiceBucket will "inherit" the methods/overrides of BucketWithPrefix and BucketWithPolicy.
### Since buckets which already bound/registered to runtime (such as default bucket) cannot participate in "override" customization, we could isolate all "override" logic to BucketBase (which is "late bound"), while leaving all other code untouched as following.
--- 3rd take ---
```go
type BucketBase interface {
Bucket
//bind a custom bucket with overrides to runtime
//outer/embedding structs should not override this
Bind(BucketBase)Bucket
}
type jsii_BucketBase struct {
*jsiiProxy_Bucket
bound bool
args []interface{}
}
//return BucketBase as base of embed/extension
func NewBucketBase(bargs ...interface{}) BucketBase {
_init_.Initialize()
return &jsii_BucketBase{&jsiiProxy_Bucket{},false,bargs...}
}
//register "customBucket" with overrides to runtime/kernel
func (bb *jsii_BucketBase) Bind(customBucket BucketBase) Bucket {
if bb.bound {
panic("bucket cannot be bound again")
}
bb.bound=true
_jsii_.Create(
FQN,
bb.args,
customBucket,
)
//since already bound, remove "Bind" method
return &struct{Bucket}{customBucket}
}
```
So custom buckets should be defined with BucketBase:
```go
type BucketWithPrefix struct {
BucketBase
prefix string
}
func NewBucketWithPrefix(bargs ...args) Bucket {
b := &BucketWithPrefix {
NewBucketBase(bargs...),
"...prefix...",
}
return b.Bind(b)
}
func (bp *BucketWithPrefix) OverrideMethod(...) {...}
```
Contributor guide
Research direction
Start by reviewing the jsii-go generated package code and the runtime/kernel registration flow described in the proposal. Determine the agreed API for separating base construction from binding, and consider the feature complete when custom bucket types can compose overrides while remaining correctly registered with the runtime.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, typescript
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100