This question already has answers here:
How to set and get fields in struct's method
(3 answers)
Closed 2 years ago.
I have created a struct Person and a method AddPerson which acts as a constructor for that struct.
package main
import "fmt"
type Person struct {
name string
salary int
balance int
}
func AddPerson(name string, salary int) Person {
p := Person{}
p.name = name
p.salary = salary
p.balance = salary
return p
}
After that I added a method spendMoney which does the following:
func (p Person) spendMoney(amountSpent int) {
p.balance = p.salary - amountSpent
fmt.Println("The amount spent is : ", amountSpent)
fmt.Println("Balance left is : ", p.balance)
}
and a main method shown below:
func main(){
p1 := AddPerson("A", 1500)
p2 := AddPerson("B", 2000)
p1.spendMoney(500)
p2.spendMoney(1000)
fmt.Println(p1.balance) //wanted to check the balance of p1 after spending.
}
I wanted to check the balance of p1 after he has spent the money, but it is still showing the same as before (i.e. 1500). I am new to Golang and come from a Python background, where this way works just fine.
You need to define the method on a pointer to your object, not to the value of your object.
func (p *Person) spendMoney(amountSpent int) {
p.balance = p.salary - amountSpent
}
Contrary to Python, you have to make the distinction between values and pointers. Values are basically copies of variables, modifying them will not make the variable itself change, unless explicitly assigning a new value to that variable.
This tutorial may make you better understand this.
Related
Let's say I have following class:
class Person() {
var age: Pair<String, Int> = Pair("person_age", 23)
// override getValue and setValue here
}
Now I want to capsulate the actual Pair and only want the user to read/write the second value of the pair. Is it possible to override the getValue and setValue methods so I can do something like this:
val p = Person()
p.age = 25
if(p.age <= 30)
Of course I can write own getter and setter methods for each property but one nice thing about Kotlin is that you have to write such less boilerplate code which will get lost then.
The following should probably already suffice:
class Person() {
var age : Int = 23 // public by default
private /* or internal */ fun toAgePair() = "person_age" to age // narrow visibility
}
So all your code accesses the age as you have shown:
val p = Person()
p.age = 25
if (p.age <= 30) ...
But if you require your Pair you just do the following instead:
p.toAgePair() // or skip that method and use: '"person_age" to p.age' instead
Alternatives to access the Pair content are: Pair.first, Pair.second or destructured, e.g.:
val myPair = Pair("person_age", 23)
// myPair.second = 25 // setting will not work however
myPair.let { (name, age) -> /* do something with it */ }
Or alternatively:
val p = Person()
val (name, age) = p.toAgePair()
// age = 25 // setting will not work however (and it wouldn't set the actual value inside the Pair if it would contain vars)
if (age < 30) // accessing is OK
However then you get access to both values which you probably didn't want in the first place, if I understood you correctly.
You could overcome the setting part using your own data class with a var but then again, you do not really gain something from it.
I wouldn't recommend you to use Pair at all. Maybe you could modify it (inherit from it, use extension functions) to suit your needs, but why try to change something as simple as Pair?. It is much easier and in this case also cleaner to just create your own class which suits your needs:
data class MyPair<out A, B>(
val first: A,
var second: B
)
val pair = MyPair("age", 1)
pair.second = 2
pair.first = 1 // error
This class has all important features which Pair has: generic types for first and second, and you can use destructuring declarations.
Now I want to capselate the actual Pair and only want the user to read/write the second value of the pair.
Assuming this means you want the first value to be final, but not the second one, there are some options.
If you only want one of the values to be writeable and readable, don't use a pair. It's not designed to be used like that. All the items of a Pair are vals.
If you want a Pair either way, can do this:
class Person(var age: Int = 23){
val pair: Pair<String, Int>
get() = Pair("person_age", age)
//Alternatively, if you don't want to use a property:
//fun getPair() = "person_age" to age
}
What this does is creating a final pair where the first value can't be modified, but the second can.
So now:
fun example(){
val person = Person()
person.age = 25;//Fine: Age is an int, and a var
//person.pair = Pair("something", 45)//fails: "Val cannot be reassigned
val pair = person.pair // Allowed. Accessing the pair still works
assert(pair.second == person.age) // This is true
}
However, if you're fine with a non-Pair solution, this works too:
data class Person (var age: Int, val string: String = "person_age")
fun example(){
val person = Person(23)
val (name, string) = person// Allowed! Just like with Pairs
person.age = 25; // Also allowed
//person.string = "something"//Not allowed
}
The n-touple unpacking is supported for data classes. If you don't have a data class, you need to declare an operator fun for each component you want to unpack. Example:
class Person (val string: String = "person_age", var age: Int){
operator fun component1() = string
operator fun component2() = age
}
But tbh, it sounds like the data class solution is the one you're looking for. It would lock the String to what it's initialized with, and because of the default value and its position, you can initialize it with a single positioned argument*
You could also use generics if you want to use the same class for multiple types.
* Assumes the code is in Kotlin. Positioned and default arguments don't work from Java code.
Here's how to overwrite a getter method in Kotlin
class Person {
var age: Int = 0
get() = if (field < 0) 0 else field
}
The attribute is accessed directly
fun main(args: Array<String>) {
val p = Person()
p.age = -28
println(p.age) //0
}
I have a tree of structs which I'd like to test using testing/quick, but constraining it to within my invariants.
This example code works:
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
type X struct {
HasChildren bool
Children []*X
}
func TestSomething(t *testing.T) {
x, _ := quick.Value(reflect.TypeOf(X{}), rnd)
_ = x
// test some stuff here
}
But we hold HasChildren = true whenever len(Children) > 0 as an invariant, so it'd be better to ensure that whatever quick.Value() generates respects that (rather than finding "bugs" that don't actually exist).
I figured I could define a Generate function which uses quick.Value() to populate all the variable members:
func (X) Generate(rand *rand.Rand, size int) reflect.Value {
x := X{}
throwaway, _ := quick.Value(reflect.TypeOf([]*X{}), rand)
x.Children = throwaway.Interface().([]*X)
if len(x.Children) > 0 {
x.HasChildren = true
} else {
x.HasChildren = false
}
return reflect.ValueOf(x)
}
But this is panicking:
panic: value method main.X.Generate called using nil *X pointer [recovered]
And when I change Children from []*X to []X, it dies with a stack overflow.
The documentation is very thin on examples, and I'm finding almost nothing in web searches either.
How can this be done?
Looking at the testing/quick source code it seems that you can't create recursive custom generators and at the same time reuse the quick library facilities to generate the array part of the struct, because the size parameter, that is designed to limit the number of recursive calls, cannot be passed back into quick.Value(...)
https://golang.org/src/testing/quick/quick.go (see around line 50)
in your case this lead to an infinite tree that quickly "explodes" with 1..50 leafs at each level (that's the reason for the stack overflow).
If the function quick.sizedValue() had been public we could have used it to accomplish your task, but unfortunately this is not the case.
BTW since HasChildren is an invariant, can't you simply make it a struct method?
type X struct {
Children []*X
}
func (me *X) HasChildren() bool {
return len(me.Children) > 0
}
func main() {
.... generate X ....
if x.HasChildren() {
.....
}
}
This is might not be such a good question, since I don't know of any compiled language that supports this feature, but since Go is constantly surprising me, I'll ask it anyway:
For my own practice, I am writing a little calculator program in Go. I'm wondering if there is a way I can declare and assign a variable of type "Operator", such that I could, for example, write:
var o Operator
o = +
var o1 Operator
o1 = /
and write function like this
func DoOperation(a,b int,o Operator) int{
return a o b
}
(No, I am not asking about operator overloading.)
Offhand, I don't know of any compiled language that supports such a thing (I'm not an expert in this). I did look at the docs under operators and found nothing. Can Go surprise me again?
Edit: The accepted answer states that Haskell supports this,
No, Go operators are not functions and hence no valid right-hand expressions. They work in a generic way e.g. the plus-operator works on all numeric types and infix-notation a la haskell is not supported either.
You would have to write your own "soft"-generic addition function using reflection.
One compiled language that covers all of your requirements is Haskell.
You can't do exactly what you say, but you can use functions instead. You have to write functions for each operator, but that's relatively little code.
type BinaryOperator func(a, b int) int
func OpAdd(a, b int) int { return a + b }
func OpSub(a, b int) int { return a - b }
func ApplyBinaryOperator(a, b int, op BinaryOperator) int {
return op(a, b)
}
Coming from an oop background I started doing this :
package main
import "fmt"
type MyInt int64
func (i * MyInt) Add(n MyInt) * MyInt {
*i += n
return i
}
func (i MyInt) String() string {
v := int64(i)
return fmt.Sprintf("0x%x (%d)", v, v)
}
func main() {
x := MyInt(10)
x.Add(10).Add(20).Add(30)
fmt.Println("x = ", x)
}
Here's an extremely simple piece of code that should work according to the documentation.
package controllers
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"fmt"
)
type TestController struct {
beego.Controller
}
type Ticket struct {
Id int `orm:"auto"`
EventId int
EntryId int
}
func (this *TestController) Get() {
o := orm.NewOrm()
tickets := new([]*Ticket)
qs, _ := o.QueryTable(new(Ticket)).Filter("EventId", 2).All(&tickets)
fmt.Print(qs)
this.Ctx.WriteString("test controller")
}
func init(){
orm.RegisterModel(new(Ticket))
}
This results in Beego crashing with the following error:
GoEventKeeper:wrong object type `*[]*controllers.Ticket` for rows scan, need *[]*rohan.com/GoEventKeeper/controllers.Ticket or *rohan.com/GoEventKeeper/controllers.Ticket
I feel like this shouldn't be happening, obviously I only have one Ticket struct inside controllers so it seems to be comparing the wrong values with eachother?
What do i need to do to resolve this?
qs, _ := o.QueryTable(new(Ticket)).Filter("EventId", 2).All(&tickets)
changes to
qs, _ := o.QueryTable(new(Ticket)).Filter("EventId", 2).All(tickets)
becasue tickets already is point
more detail please refer http://beego.me/docs/mvc/model/query.md#all
This question already has answers here:
Objective-C Blocks, Recursion Fails
(3 answers)
Closed 9 years ago.
I love JavaScript's ability to define functions as variables and am trying to do something similar in Objective-C. In particular, I want to write a recursive function using an anonymous block that I can call on an object and have it work its way through a tree, applying a change at each node:
void ( ^setDetailsLoaded )( Product* ) = ^void ( Product* prod ) {
prod.detailsLoaded = true;
for ( Group* group in prod.groups ) {
for ( Product* mod in group.mods )
setDetailsLoaded( mod );
}
};
setDetailsLoaded( product ); <-- error here
However, I'm getting the strange error error: address doesn't contain a section that points to a section in a object file[sic] when I run the program (which compiles fine).
I'm just wondering if perhaps I need to retain the block or something, or if I should just do this with function pointers instead of blocks.
Because of the way blocks are implemented—they make a const copy of all primitive type variables, and a strong reference to all object type variables referenced in them at creation time—attempting to recursively reference a block within itself will result in the crash that you saw.
You can solve this by using the __block annotation on the block variable itself:
__block void ( ^setDetailsLoaded )( Product* ) = ^void ( Product* prod ) {
prod.detailsLoaded = true;
for ( Group* group in prod.groups ) {
for ( Product* mod in group.mods )
setDetailsLoaded( mod );
}
};
See #bbum's blog post on blocks for more details (specifically tip #7).