calling method from struct in swift - methods

I found what looks like an elegant solution to iterating over enums here: How to enumerate an enum with String type?
Next, I'm having trouble figuring out how to call this method. At face value, it doesn't look like it takes an argument, but when I try to call Card.createDeck() I get a compiler error telling me "error: missing argument for parameter #1 in call".
Please let me know what I'm doing wrong here? What am I supposed to pass to this method?
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
func createDeck() -> [Card] {
var deck = [Card]()
var n = 1
while let rank = Rank.fromRaw(n) {
var m = 1
while let suit = Suit.fromRaw(m) {
deck += Card(rank: rank, suit: suit)
m++
}
n++
}
return deck
}
}

createDeck() is a instance method. Doing Card.createDeck() is a call to a class method that doesn't exist.
class func - for class methods
Edit:
I misread that it was a struct, but the same logic applies.
static func - for static methods

You can not able to call it directly as you need instace of struct as it is not class function.So use
Card(rank:Rank.yourRank,suit:Suit.yourSuit).createDeck()
Actually to make struct you need rank and suit instance so first make them and than pass to Card constructor.By default struct have arguments as their properties.

Related

How to distinguish between reference and value in golang

package main
type A struct {
Num int
}
func getA() A {
return A{Num: 10}
}
func main() {
if getA().Num == 10 {
// getA().Num = 20 // why not working
myA := getA()
myA.Num = 20
}
}
why "getA().Num = 20" line do not working?
I'm don't know the difference between
myA := getA()
myA.Num = 20
and
//getA().Num = 20 // why not working
I think it just two line and one line...
I'm more familiar with Java.
What I need to know to understand it?
I expected the code working correctly....
Tweak your function declaration like this, and it will work as you're expecting:
func getA() *A {
return &A{Num: 10}
}
What has changed is that getA returns a pointer to a value of type A.
In Java, class data types are always used as references (like a pointer), except the language doesn't use an explicit notation like this. So, writing Go code to use pointer types like *A is similar to what you're used to in Java.
The part that may confuse you is that Java doesn't have a direct equivalent for Go's non-pointer types, like the plain A in your Go code. In Java, you can only declare a class type, which always acts as a reference.

Naming receiving variables from a multiple return function

Go allows for multiple named return values, but what about the receiving variables? Are they protected when return values are juggled around?
Let's say we start with this:
func foo() (i int, j int) {
i = 1
j = 2
return
}
a, b := foo()
Now what if some other coder comes by and makes the following change to foo's definition:
func foo() (j int, i int) {
my calling function is invalidated. Is it, then, possible to name the returned values from the calling side as well. For instance, if I called it like this:
(a:i, b:j) := foo()
then I would be attaching them to the named return values, rather than assigning them in the order they are returned.
So, is there a way to solve that problem?
This is no different than rearranging the input parameters. As a rule, don't do that unless you intend to make a breaking change. But if you want to deal with things by name rather than position, you want a struct. For example, you can use anonymous structs:
func foo() struct {
i int
j int
} {
return struct {
i int
j int
}{1, 2}
}
func main() {
result := foo()
fmt.Println(result.i, result.j)
}
Of course you can also name the struct if you used it in other places, but there's no need if you just want to name the fields.

How to use runtime.Object to create CRD generic functions in go [duplicate]

I have an interface Model, which is implemented by struct Person.
To get a model instance, I have the following helper functions:
func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}
func newPerson() *Person {
return &Person{}
}
The above approach allows me to return a properly typed Person instance (can easily add new models later with same approach).
When I attempted to do something similar for returning a slice of models, I get an error. Code:
func newModels(c string) []Model {
switch c {
case "person":
return newPersons()
}
return nil
}
func newPersons() *[]Person {
var models []Person
return &models
}
Go complains with: cannot use newPersons() (type []Person) as type []Model in return argument
My goal is to return a slice of whatever model type is requested (whether []Person, []FutureModel, []Terminator2000, w/e). What am I missing, and how can I properly implement such a solution?
This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643
The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.
A []Person and a []Model have different memory layouts. This is because the types they are slices of have different memory layouts. A Model is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person is a struct whose size depends on the fields it contains. In order to convert from a []Person to a []Model, you will need to loop over the array and do a type conversion for each element.
Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.
models := make([]Model, len(persons))
for i, v := range persons {
models[i] = Model(v)
}
return models
And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.
*[]Person // pointer to slice
[]*Person // slice of pointers
Maybe this is an issue with your return type *[]Person, where it should actually be []*Person so to reference that each index of the slice is a reference to a Person, and where a slice [] is in itself a reference to an array.
Check out the following example:
package main
import (
"fmt"
)
type Model interface {
Name() string
}
type Person struct {}
func (p *Person) Name() string {
return "Me"
}
func NewPersons() (models []*Person) {
return models
}
func main() {
var p Model
p = new(Person)
fmt.Println(p.Name())
arr := NewPersons()
arr = append(arr, new(Person))
fmt.Println(arr[0].Name())
}
As Stephen already answered the question and you're a beginner I emphasize on giving advises.
A better way of working with go's interfaces is not to have a constructor returning
the interface as you might be used to from other languages, like java, but to have
a constructor for each object independently, as they implement the interface implicitly.
Instead of
newModel(type string) Model { ... }
you should do
newPerson() *Person { ... }
newPolitician() *Politician { ... }
with Person and Politician both implementing the methods of Model.
You can still use Person or Politician everywhere where a Model
is accepted, but you can also implement other interfaces.
With your method you would be limited to Model until you do a manual conversion to
another interface type.
Suppose I have a Person which implements the method Walk() and a Model implements ShowOff(), the following would not work straight forward:
newModel("person").ShowOff()
newModel("person").Walk() // Does not compile, Model has no method Walk
However this would:
newPerson().ShowOff()
newPerson().Walk()
As others have already answered, []T is a distinct type. I'd just like to add that a simple utility can be used to convert them generically.
import "reflect"
// Convert a slice or array of a specific type to array of interface{}
func ToIntf(s interface{}) []interface{} {
v := reflect.ValueOf(s)
// There is no need to check, we want to panic if it's not slice or array
intf := make([]interface{}, v.Len())
for i := 0; i < v.Len(); i++ {
intf[i] = v.Index(i).Interface()
}
return intf
}
Now, you can use it like this:
ToIntf([]int{1,2,3})
Types T and []T are distinct types and distinct are their methods as well, even when satisfying the same interface. IOW, every type satisfying Model must implement all of the Model's methods by itself - the method receiver can be only one specific type.
Even if Go's implementation allowed this, it's unfortunately unsound: You can't assign a []Person to a variable of type []Model because a []Model has different capabilities. For example, suppose we also have Animal which implements Model:
var people []Person = ...
var models []Model = people // not allowed in real Go
models[0] = Animal{..} // ???
var person Person = people[0] // !!!
If we allow line 2, then line 3 should also work because models can perfectly well store an Animal. And line 4 should still work because people stores Persons. But then we end up with a variable of type Person holding an Animal!
Java actually allows the equivalent of line 2, and it's widely considered a mistake. (The error is caught at run time; line 3 would throw an ArrayStoreException.)

Is there a constructor interface for a struct type?

In golang, say I have a type that needs some setup done on it before use beyond just setting default values. ex:
type dice struct {
input string
count int
sides int
result int
}
func (d *dice) Roll() {
//initialize random seed
rand.Seed(time.Now().UnixNano())
for i := 0; i < d.count; i++ {
d.result = d.result + rand.Intn(d.sides)+1)
}
}
Simple example but say if I wanted to have d.Roll() called automatically when creating an instance of the 'dice' type is there a way to do that? More in line with the issue I'm trying to solve, say I wanted the rand.Seed(time.Now().UnixNano()) bits to be called automatically before I call Roll() is there an idiomatic golang way to do this?
Basically "How do you handle constructor functionality in golang?" is my question. Is there an interface for this I can add?
No, Go doesn't provide this kind of interface. You just can't use a constructor like you would do in C++ by example.
The current idiom is to create a function
NewX(args...) X // or *X
in which you can setup your struct as you want. In your case, it could look like this:
func NewDice() dice {
var d dice
d.Roll()
return d
}
There is not. But the common, and I would say idiomatic, thing to do is to put a func NewDice() dice in your package and then you can just call it to get an instance. Do your set up there. It serves the same purpose as a constructor. It's pretty common to have package level methods like NewMyType that do initilization and return and instance.

slice of struct != slice of interface it implements?

I have an interface Model, which is implemented by struct Person.
To get a model instance, I have the following helper functions:
func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}
func newPerson() *Person {
return &Person{}
}
The above approach allows me to return a properly typed Person instance (can easily add new models later with same approach).
When I attempted to do something similar for returning a slice of models, I get an error. Code:
func newModels(c string) []Model {
switch c {
case "person":
return newPersons()
}
return nil
}
func newPersons() *[]Person {
var models []Person
return &models
}
Go complains with: cannot use newPersons() (type []Person) as type []Model in return argument
My goal is to return a slice of whatever model type is requested (whether []Person, []FutureModel, []Terminator2000, w/e). What am I missing, and how can I properly implement such a solution?
This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643
The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.
A []Person and a []Model have different memory layouts. This is because the types they are slices of have different memory layouts. A Model is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person is a struct whose size depends on the fields it contains. In order to convert from a []Person to a []Model, you will need to loop over the array and do a type conversion for each element.
Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.
models := make([]Model, len(persons))
for i, v := range persons {
models[i] = Model(v)
}
return models
And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.
*[]Person // pointer to slice
[]*Person // slice of pointers
Maybe this is an issue with your return type *[]Person, where it should actually be []*Person so to reference that each index of the slice is a reference to a Person, and where a slice [] is in itself a reference to an array.
Check out the following example:
package main
import (
"fmt"
)
type Model interface {
Name() string
}
type Person struct {}
func (p *Person) Name() string {
return "Me"
}
func NewPersons() (models []*Person) {
return models
}
func main() {
var p Model
p = new(Person)
fmt.Println(p.Name())
arr := NewPersons()
arr = append(arr, new(Person))
fmt.Println(arr[0].Name())
}
As Stephen already answered the question and you're a beginner I emphasize on giving advises.
A better way of working with go's interfaces is not to have a constructor returning
the interface as you might be used to from other languages, like java, but to have
a constructor for each object independently, as they implement the interface implicitly.
Instead of
newModel(type string) Model { ... }
you should do
newPerson() *Person { ... }
newPolitician() *Politician { ... }
with Person and Politician both implementing the methods of Model.
You can still use Person or Politician everywhere where a Model
is accepted, but you can also implement other interfaces.
With your method you would be limited to Model until you do a manual conversion to
another interface type.
Suppose I have a Person which implements the method Walk() and a Model implements ShowOff(), the following would not work straight forward:
newModel("person").ShowOff()
newModel("person").Walk() // Does not compile, Model has no method Walk
However this would:
newPerson().ShowOff()
newPerson().Walk()
As others have already answered, []T is a distinct type. I'd just like to add that a simple utility can be used to convert them generically.
import "reflect"
// Convert a slice or array of a specific type to array of interface{}
func ToIntf(s interface{}) []interface{} {
v := reflect.ValueOf(s)
// There is no need to check, we want to panic if it's not slice or array
intf := make([]interface{}, v.Len())
for i := 0; i < v.Len(); i++ {
intf[i] = v.Index(i).Interface()
}
return intf
}
Now, you can use it like this:
ToIntf([]int{1,2,3})
Types T and []T are distinct types and distinct are their methods as well, even when satisfying the same interface. IOW, every type satisfying Model must implement all of the Model's methods by itself - the method receiver can be only one specific type.
Even if Go's implementation allowed this, it's unfortunately unsound: You can't assign a []Person to a variable of type []Model because a []Model has different capabilities. For example, suppose we also have Animal which implements Model:
var people []Person = ...
var models []Model = people // not allowed in real Go
models[0] = Animal{..} // ???
var person Person = people[0] // !!!
If we allow line 2, then line 3 should also work because models can perfectly well store an Animal. And line 4 should still work because people stores Persons. But then we end up with a variable of type Person holding an Animal!
Java actually allows the equivalent of line 2, and it's widely considered a mistake. (The error is caught at run time; line 3 would throw an ArrayStoreException.)

Resources