Is there a Go equivalent of PHP's __toString method? - go

In php exists a __toString() method that allow to make a taylored representation of an object. For example:
final class Foo
{
public function __toString()
{
return "custom representation";
}
}
$foo = new Foo();
echo $foo; // this will output "custom representation"
In Go it is possible to create a struct:
type Person struct {
surname string
name string
}
sensorario := Person{
"Senso",
"Rario",
}
fmt.Println(sensorario) // this will output "{Senso Rario}"
It is possible to add a toString method to the struct?
EDIT:
I've found this solution:
func (p *Person) toString() string {
return p.surname + " " + p.name
}
fmt.Println(simone.toString())
But what I am looking for, is the way to replace
fmt.Println(simone.toString())
with
fmt.Println(simone)

I think you're looking for the Stringer interface.
type Stringer interface {
String() string
}
Any type that implements this interface will be automatically stringified using it by many different libraries, obviously including the fmt package, and will indeed work in your example of fmt.Println.

Related

How to define generic function with custom structs without listing all of them?

Let's say I have two different structs:
type One struct {
Id string
// Other fields
}
type Two struct {
Id string
// Other fields
}
Is it possible to define a function that accepts both One and Two without explicitly listing them as options?
E.g. I am looking for something like this:
type ModelWithId struct {
Id string
}
func Test[M ModelWithId](m M) {
fmt.PrintLn(m.Id)
}
one := One { Id: "1" }
Test(one) // Prints 1
I don't want to use funcTest[M One | Two](m M), because I'll likely have 10+ structs and I don't want to come back to the function every time I add a new struct to the codebase.
Generics constraints the type parameter behaviours using methods, so you need to rewrite your code as:
type One struct {
id string
}
func (o *One) Id() string {
return o.id
}
then your use site would become:
type ModelWithId interface {
Id() string
}
func Test[M ModelWithId](m M) {
fmt.Println(m.Id())
}

Method taking interface as a parameter inside interface

I am declcaring an interface in go
type comparable interface {
GetKey() float32
Compare(comparable) int
}
and implementing this interface by creating this structure
type Note struct {
id int
text string
priority float32
}
func (note Note) GetKey() float32 {
return note.priority
}
func (note Note) Compare(note2 Note) int {
if note.priority < note2.priority {
return -1
} else if note.priority > note2.priority {
return 1
} else {
return 0
}
}
But when I am passing note object into a function which accepts comparable interface as a parameter I am getting "Wrong type for method compare" error.
Am I missing something or doing something wrong? Please help
Thanks in advance
You are not implementing comparable since you use Note in compare method not comparable. Compare(note2 Note) is not same as Compare(comparable).
Use comparable in Compare method to implement comaprable interface
func (note Note) Compare(note2 comparable) int {
if note.GetKey()< note2.GetKey() {
return -1
} else if note.GetKey()> note2.GetKey() {
return 1
} else {
return 0
}
}
You declared comparable as having a method with signature Compare(comparable) int.
So func (note Note) Compare(note2 Note) ought to be func (note Note) Compare(note2 comparable), to match the interface.
Otherwise, you're not implementing the same interface. To implement comparable, your Compare method needs to take any comparable, but the one you declared for Note takes only Note, and not any comparable. It's a different method.
Here's a modified-to-work, minimal example based on your code: https://play.golang.org/p/ajH1s5gbGcQ

What is the concept of this interface and private data type pattern

I used the github.com/hooklift/gowsdl/soap , and I got generated code with this pattern
package funky
import (
"fmt"
)
type Place struct {
Text string
}
type RandomFunky interface {
Buggy(b int)(int)
}
type randomFunky struct {
place *Place
}
func NewFunky(p *Place) RandomFunky {
return &randomFunky{
place: p,
}
return nil
}
func (rf * randomFunky) Buggy(b int)(int) {
fmt.Println(rf.place.Text)
return b
}
package main
import (
"fmt"
"funky"
)
func main() {
p := funky.Place{}
p.Text = "o jee"
f := funky.NewFunky(&p)
fmt.Printf("%T\n",f) // type of "*funky.randomFunky"
// var f *funky.randomFunky !!! cannot refer to unexported name funky.randomFunky
f.Buggy(1)
}
"f" - I can get this type this way, but I can not create a var of this type!
What if I want to store *funky.randomFunky var in the struct ?
Or pass it to the function?
Is this implies that I always have to recreate NewFunky every time I want to call Buggy method?
(assuming Buggy called in multiple places and/or interface has more methods)
Or should I modify the code and make *funky.randomFunky public?
Or else?
So the idea is that any variable/function/type/method starting with lowercase is local, and starting with uppercase is global. Local stuff can be used directly only inside the same package.
So in your case, RandomFunky is a global interface with a single method Buggy, and a randomFunky is a local structure, implementing RandomFunky, because it has the method Buggy with the same parameters.
In fact, NewFunky returns you a structure wrapped into an interface. So you can't use randomFunky outside the package funky, but you can use funky.RandomFunky.
In your case you can just create a variable of this type
...
var f funky.RandomFunky
f = funky.NewFunky(&p)
...

How to write a reusable transform for String to Enum value across a group of Enum classes? (Kotlin)

I have a group >5 of Enum classes that take String parameter in its values, and I want to have simple code for all these Enum classes to convert from a String field in JSON object.
enum class Religiousness(val jsonStr: String, val resID: Int) {
NotAtAll("none", R.string.not_religious),
Somewhat("somewhat", R.string.somewhat_religious),
Very("very", R.string.very_religious),
;
override fun toString() = jsonStr
fun displayString(res: Resources) = res.getString(resID)
}
I want to be able to write code like this
fun JsonConvertStrToEnum(enumClass: Class<Enum<*>>, str: String): Enum<*> {
for (enumval in enumClass.enumConstants) {
if ((enumval as IJsonStringConvertible).jsonStr() == str)
return enumval
}
throw IllegalArgumentException("Gave an invalid enum value for class ${enumClass.canonicalName}")
}
I am having a hard time figuring out if IJsonStringConvertible can work, and what its definition would be, and how to implement it in the Enum value instances. Any advice?
Update: I have now written the converter as this. Is this the best way? Can I also express that the return value is a subtype of the parameter so don't need to cast return value?
fun JsonConvertStrToEnum(enumClass: Class<out Enum<*>>, str: String): Enum<*> {
for (enumval in enumClass.enumConstants) {
if (enumval.toString() == str)
return enumval
}
throw IllegalArgumentException("Gave an invalid enum value for class ${enumClass.canonicalName}")
}
Enums as other classes can implement interfaces like so:
interface IJsonStringConvertible {
val jsonStr:String
}
enum class Religiousness(override val jsonStr: String, val resID: Int) : IJsonStringConvertible {
NotAtAll("none", R.string.not_religious),
Somewhat("somewhat", R.string.somewhat_religious),
Very("very", R.string.very_religious),
;
override fun toString() = jsonStr
fun displayString(res: Resources) = res.getString(resID)
}
Which would then be used as:
for (enumval in enumClass.enumConstants) {
if ((enumval as IJsonStringConvertible).jsonStr == str)
return enumval
}
However the above lookup can be expensive (if used millions of times). Take a look at the reverse lookup question to find out how to do it more efficiently.
If it helps anyone, here's the final version in my production app.
fun <EnumT : Enum<EnumT>> ConvertStrToEnum(enumClass: Class<EnumT>, str: String?): EnumT? {
if (str == null)
return null
for (enumval in enumClass.enumConstants) {
if (enumval.toString() == str)
return enumval
}
throw IllegalArgumentException("Gave an invalid enum value for class ${enumClass.canonicalName}")
}
fun <EnumT : Enum<EnumT> > ConvertStrArrayToEnumSet(enumClass: Class<EnumT>, array: List<String>?) : EnumSet<EnumT> {
val set = EnumSet.noneOf(enumClass)
array?.forEach { value -> set.add(ConvertStrToEnum(enumClass, value)) }
return set
}

How in Swift specify type constraint to be enum?

I want to specify a type constraint that the type should be a raw value enum:
enum SomeEnum: Int {
case One, Two, Three
}
class SomeProtocol<E: enum<Int>> { // <- won't compile
func doSomething(e: E) {
compute(e.toRaw())
}
}
How can I do it in Swift? (I used the F# syntax for example)
enum SomeEnum: Int {
case One, Two, Three
}
class SomeClass<E: RawRepresentable where E.RawValue == Int>{
func doSomething(e: E) {
print(e.rawValue)
}
}
class SomeEnumClass : SomeClass<SomeEnum> {
}
or directly
class SomeOtherClass{
func doSomething<E: RawRepresentable where E.RawValue == Int>(e: E) {
print(e.rawValue)
}
}
UPDATE for swift3:
enum SomeEnum: Int {
case One, Two, Three
}
class SomeClass<E: RawRepresentable> where E.RawValue == Int {
func doSomething(e: E) {
print(e.rawValue)
}
}
class SomeEnumClass : SomeClass<SomeEnum> {
}
resp.
class SomeOtherClass{
func doSomething<E: RawRepresentable>(e: E) where E.RawValue == Int {
print(e.rawValue)
}
}
While you can place enums into a generic type without contraints (<T>), it's not possible to create constraints for all enums or all structs. All the constraints are based on interfaces (subclassing, protocols). Unfortunately, there is nothing in common between two random structs or two random enums.
Structs and enums can't inherit from other structs/enums so the only constraints for enums must be based on protocols.
protocol EnumProtocol {
func method()
}
enum TestEnum : Int, EnumProtocol {
case A
case B
func method() {
}
}
enum TestEnum2 : Int, EnumProtocol {
case C
func method() {
}
}
class EnumGeneric <T : EnumProtocol> {
func method(a: T) {
a.method()
}
}
let test = EnumGeneric<TestEnum>()
test.method(TestEnum.A)
Also note that all enums "inheriting" from a primitive type like Int conform to RawRepresentable, so you could
class EnumGeneric <T : RawRepresentable> {
func method(a: T) {
println("\(a.toRaw())");
}
}
but that won't work for enums declared as enum TestEnum {
AFAIK, Swift does not support type constraint to be specified with enums.
Cited from Swift Manual
Type Constraint Syntax
You write type constraints by placing a single class or protocol
constraint after a type parameter’s name, separated by a colon, as
part of the type parameter list. The basic syntax for type constraints
on a generic function is shown below (although the syntax is the same
for generic types):
Strictly limited to a class or protocol unless there's some hidden features which is not mentioned in manual. As far as I tested, struct or enum are all prohibited by the compiler.
enum Test1 : Int
{
case AAA = 0
}
func test1f<T:Test1>(a: Test1) {} // error: Inheritance from non-protocol, non-class type 'Test1'
struct Test2
{
var aaa:Int = 0
}
func test2f<T:Test2>(a: Test2) {} // error: Inheritance from non-protocol, non-class type 'Test1'
class Test3
{
}
func test3f<T:Test3>(a: Test3) {} // OK

Resources