What does a type name in parentheses before a variable mean?
I am having a bit of trouble understanding this piece of code. It is from a book I am reading but I feel like the guy is just telling me to type stuff without explaining it in much depth.
- (IBAction)sliderCh开发者_Go百科anged:(id)sender
{
UISlider *slider = (UISlider *)sender; //set slidervar as active slider
int progressAsInt = (int)(slider.value + 0.5f);
NSString newText = [[NSString alloc] initWithFormat:@"%d",progressAsInt];
sliderLabel.text = newText;
[newText release];
}
the issue is with the first line
UISlider *slider = (UISlider *)sender; //set slidervar as active slider
I do not understand what typecasting is, which is what the guy says in the book. "avoids needing to typecast sender everytime we use it"
I also do not understand what/why the second line has int
in brackets. I am used to having code like
int progressAsInt = 56
Typecasting is a method of telling the compiler that something is a different type than it is. It is involved in both parts of your question. You cast something by placing the new type in parentheses before the item you are casting.
UISlider *slider = (UISlider *)sender;
When the method is declared, sender
has a type of id
. Since you know it is supposed to be a slider, you cast it to UISlider *
and store it in a variable with that type so that the compiler doesn't give you warnings when you try to use slider specific properties.
int progressAsInt = (int)(slider.value + 0.5f);
Here, slider.value
is a floating point number. Since you want to store it in an integer type, you need to cast it. When a float is cast to an int, it is automatically rounded toward zero. The code wanted it rounded to the nearest integer, so it added 0.5 before casting.
Your problem is that you don't understand C. Objective-C is a thin layer over C that adds classes and messaging. Check a good C book, such as one from "The Definitive C Book Guide and List".
Without obtaining a reference to the object that is typed as UISlider *
, you would be unable to use the property syntax without, at each instance, casting the sender
reference to the desired type, for example, ((UISlider *)sender).value
. Even if you weren't using property dot notation, a cast would also be necessary to get the compiler to treat [slider value]
as returning anything other than an id
.
The book as is just being silly, though. There's no requirement that the argument to an action method be typed as id
. When you know that the sender is always going to be of a certain type – as in this case, where the code assumes that sender
is always going to be a kind of UISlider
– you can just use that type in the method declaration:
- (IBAction)sliderChanged:(UISlider *)sender
{
/* code */
}
This better documents the programmer's intent – documentation that Interface Builder picks up on – as well as completely eliminating the need to do any casting within the method.
In general, if you need to typecast, there's a good chance you're doing something wrong.
As another example, let's look at this line:
int progressAsInt = (int)(slider.value + 0.5f);
Here, the explicit int
typecast is unnecessary. Because the assignment is to an int
lvalue, the floating point value that results from the addition would necessarily be coerced to an int
as part of the assignment.
Basically, the computer (compiler, actually, but we can pretend for simplicity's sake) only knows what kind of thing you are referring to because of its "type". The type could be an int, or
UISlider *`, or any number of other things. It is a classification for a variable.
At the top, you can see that sender
is of type id
, which means the computer has no idea what kind of object it is.
When this method is called, you receive an object which is called sender
. But even though you know that sender is a UISlider*
, you can't call UISlider methods on it, because the computer doesn't know that.
When you say UISlider *slider = (UISlider *)sender;
, you are saying "Hey computer, I'm telling you that sender is a UISlider *
, and I'm going to refer to it as slider
from now on. That is what typecasting is.
The same goes for int progressAsInt = (int)(slider.value + 0.5f);
(slider.value + 0.5f)
is actually a float
, which is alike a number with decimals. You can't just assign a float to a variable meant for int
s, so instead you say "Please turn this float into an int for me", by putting the (int)
in front.
精彩评论