Friday, May 17, 2024
HomeGolangPolymorphic Clone() utilizing generics? - Getting Assist

Polymorphic Clone() utilizing generics? – Getting Assist


Attempting to create a Clone() operate with returns the “ultimate” concrete kind and utilizing a reference to polymorphically create a clone of the ultimate kind, however hitting compile errors. Concepts/resolution appreciated.

Is it potential to make the code under compile or is there an idiomatic method to obtain the polymorphic cloning with embedding of interface/struct ?

package deal principal

import "fmt"

kind Cloner[T any] interface {
	Clone() T
}

kind AI[T any] interface {
	// Need all implementations to have a Clone() technique that returns the ultimate kind
	Cloner[AI[T]]
}

// implements the AI interface, by embedding the interface
kind AS struct {
	AI[int]
	a int
}

func (as AS) Clone() AS {
	return AS{a: as.a}
}

// implements the AI interface, by embedding the interface
kind BS struct {
	AI[int]
	b string
}

func (bs BS) Clone() BS {
	return BS{b: bs.b}
}

// implements the AI interface by embedding AS struct
kind CS struct {
	AS
	c int
}

func (cs CS) Clone() CS {
	return CS{
		AS: cs.Clone(), // error: can not use cs.Clone() (worth of kind CS) as kind AS in struct literal
		c:  cs.c,
	}
}


func principal() {
	var aiRef AI[int]

	// attempt to get a clone of concrete objects

	aiRef = &AS{a: 10}
	fmt.Printf("AS: %#vn", aiRef.Clone())
	// Compile error:
	//  ./principal.go:42:10: can not use &AS{…} (worth of kind *AS) as kind AI[int] in project:
	//  *AS doesn't implement AI[int] (mistaken kind for Clone technique)
	//  have Clone() AS
	//  need Clone() AI[int]

	aiRef = &BS{b: "hey"}
	fmt.Printf("BS: %#vn", aiRef.Clone())
	// similar compile error as above

	aiRef = &CS{c: 10}
	fmt.Printf("CS: %#vn", aiRef.Clone())
	// similar compile error as above
}

Hello @globalflea,

I simply posted a solution to the same query right here. This may additionally apply to your state of affairs.

Hello,

Thanks, however it didn’t clear up this set of issues. i’ve nonetheless have an issue attempting to create an occasion of the ‘derived’ kind. or quite i don’t know easy methods to declare a definition that can require little one struct to have a Clone that returns the kid kind

particularly, how do i guarantee all little one to have a clone operate?

kind AI[T any] interface {
	// Need all implementations to have a Clone() technique that returns the ultimate kind

	Cloner[AI[T]] 
	// ?? The right way to declare a generic Clone() to be applied by kids?
	// ??   particularly, since i will not know what is the precise little one kind 
}

suppose with Rust, i may have declare one thing like Clone() -> Self

Additionally in the primary(),

	var aiRef AI[int]

	aiRef = &AS{a: 10}
	//   ./principal.go:56:10: can not use &AS{…} (worth of kind *AS) as kind AI[int] in project:
	//   *AS doesn't implement AI[int] (mistaken kind for Clone technique)
	//   have Clone() AS
	//   need Clone() AI[int]

Famous, with thanks that the CloneAny() works for calling the Clone() operate for little one structs

	// fmt.Printf("AS: %#vn", aiRef.Clone()) // had compile error earlier
	fmt.Printf("AS: %#vn", CloneAny(aiRef)) // utilizing CloneAny eliminated the error

Hey each. Don’t have an answer however want to share a thought:

easy methods to declare a definition that can require little one struct to have a Clone that returns the kid kind

Is it potential that you just’re putting an excessive amount of emphasis on forcing structs to do one thing as a substitute of limiting operations to obtain sure varieties?

In different phrases, as a substitute of forcing little one structs to have a clone, why not restrict your self to require some operations to just accept Cloner[T]?

func SomethingWithClone[T Cloner[T]](c T) T {
	// ...
	return c.Clone()
}

Forcing varieties to implement one thing is the kind of pondering I’ve in languages like Scala and Java, however with Go’s inheritance I are inclined to focus extra on “This operation ought to settle for arguments which can be able to …”


Possibly this isn’t potential?

I don’t know if what you’re attempting to do is feasible, as a result of strategies can’t have kind parameters and interfaces are applied in strategies. So requiring a sort to have AI[int] appears inconceivable (at first look) as a result of the tactic doesn’t have kind parameters.

There’s additionally one thing within the feedback you shared that I feel may very well be mistaken (however not totally positive, semantically): implements the AI interface, by embedding the interface afaik, interfaces aren’t applied by embedding except you’re embedding a struct that already implements it. On this case you’re embedding the interface kind straight.

Anyhow, that is attention-grabbing and I don’t know sufficient but, I’m going to learn up on the generics thingy to see if some mild is shed in my mind.


Sidebar:

I feel the Clone in CS:

func (cs CS) Clone() CS {
	return CS{
		AS: cs.Clone(), // error: can not use cs.Clone() (worth of kind CS) as kind AS in struct literal
		c:  cs.c,
	}
}

Must be:

func (cs CS) Clone() CS {
	return CS{
		AS: cs.AS.Clone(),
		c:  cs.c,
	}
}

And the error there goes away

1 Like

This subject was routinely closed 90 days after the final reply. New replies are not allowed.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments