Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support extending generic type #31

Open
nati opened this issue Mar 10, 2017 · 1 comment
Open

support extending generic type #31

nati opened this issue Mar 10, 2017 · 1 comment

Comments

@nati
Copy link

nati commented Mar 10, 2017

Hi.
Thank you for your providing a neat package!

I would like to extend generic type like this Java example so that I can call method in the
type.

public class Bar<T extends B & java.io.Serializable> {}

and I find I could do similar stuff with Genny. but it is a bit hacky way.

package genny

import "bytes"

// NOTE: this is how easy it is to define a generic type

//Something ..
type Something interface { //generic.Type
	String() string //generic.Type
} //generic.Type

// SomethingQueue is a queue of Somethings.
type SomethingQueue struct {
	items []Something
}

func NewSomethingQueue() *SomethingQueue {
	return &SomethingQueue{items: make([]Something, 0)}
}

func (q *SomethingQueue) Push(item Something) {
	q.items = append(q.items, item)
}

func (q *SomethingQueue) Pop() Something {
	item := q.items[0]
	q.items = q.items[1:]
	return item
}

func (q *SomethingQueue) String() string {
	var buf bytes.Buffer
	for _, item := range q.items {
		buf.WriteString(item.String())
	}
	return buf.String()
}

How about support this use case officially, and add "generic.ignore" for ignoring line?

@ThinCats
Copy link

ThinCats commented Sep 13, 2019

I think it's a bit difficult to implement the same syntax as Java :), but we can use the golang style to nest the interface.

In your example, you can use existed interface defined in other packages

(The following code will work on genny df3d48a)

package genny
import (
  "bytes"
  "fmt"
)

type Something interface {
  fmt.Stringer
}

type SomethingQueue struct {
  items []Something
}

...

func (q *SomethingQueue) String() string {
  var buf bytes.Buffer
	for _, item := range q.items {
		buf.WriteString(item.String())
	}
	return buf.String()
}

It's also easy to extend other interfaces, like json.Marshaler. We can also nest with generic.Type to indicate the interface is generic

type Something interface {
  generic.Type

  json.Marshaler
  fmt.Stringer
}

We can do this because genney will replace the string identifier of the file, regardless of its actual type. In this way, we can extend more complex types while being type-safe.

I have summarized several common usages used in my toy project.

  1. Type Object extends to struct (has fields)
type Object struct {
  generic.Type

  name string
  age int
}

// Now you can use it in function without compile errors
func doSomeThing(o *Object) (string, int) {
  ...
  return o.name, o.age
}
  1. Type Object extends to interface (has method)
type Object interface {
  generic.Type // can be removed

  run() Object
  stop() Object
}

// use it as normal interface
func operate(o Object) {
  o.run().stop()
}
  1. Mock package
// file1: demo.go
type mockPackage struct {
  // package function
  Log(...interface{}) error
  // package exported variable
  ColorRed int
  ColorGreen int
  // Not find a way to mock exported Type
}

var PackageName mockPackage

// file2: demo_template.go
// Use in another file
func normalFunc() {
  PackageName.Log("Hello", "Good")
  color := PackageName.ColorGreen
  ...
}

// use command
// geeny -in=demo_template.go -out=gen_demo.go gen "PackageName=mypkg"

Hope to be helpful :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants