preface
When writing custom controls, you sometimes need to perform operations on the PointF object to calculate the horizontal and vertical spacing between two points.
Simplifying the requirement is all about figuring out the difference between the two points.
The code implementation looks something like this
fun minusPoint(p1: PointF, p2: PointF): Return PointF(dx, dy) {val p = minusPoint(p1,p2)}Copy the code
First Modification
This is way too Java, because we’re using Kotlin, so we can do this instead
Fun minusPoint(p1: PointF, p2: PointF): PointF = PointF(p1.x-p2.x, p1.y-p2.y)Copy the code
Second Modification
Of course, that’s not good enough. We use Kotlin’s extension function to add an extension function to the PointF object
Funtf.minuspoint (p2: PointF): PointF = PointF(this.x-p2.x, this.y-p2.y) // Use val p = p1.minuspoint (p2)Copy the code
Such calls look much more readable.
Third Revision
Because PointF comes with an offset method
public final void offset(float dx, float dy) {
x += dx;
y += dy;
}
Copy the code
So we can change it to something like this
Funtf.minuspoint (p2: PointF): PointF = PointF().apply {this.offset(-p2.x, -p2.y)} // use val p = p1.minuspoint (p2)Copy the code
Fourth Modification
For those of you with programming experience, one of the “problems” with this function is that it creates a new PointF object every time. So we can optimize it again.
Fun pointf.minusPoint (p2: PointF): PointF = this.apply {this.offset(-p2.x, -p2.y)}Copy the code
This way, no new object is created for each call, and the original object is used. Everything looks wonderful.
Fifth Revision
Let’s go back to where we started, and the problem we started with was “compute the difference between two points,” so semantically speaking. Is it possible to simply describe it like this
val p1: Point
val p2: Point
val p = p1 - p2
Copy the code
Those of you who know Kotlin’s operator probably thought of the – operator from the first time you saw the requirement.
The PointF extension operator is obviously in KTX.
/** * Offsets this point by the negation of the specified point and returns the result * as a new point. */ inline Operator fun pointf. minus(p: PointF): PointF {return PointF(x, y). Apply {offset(-p.x, -p.y)}} // Use val p = p1-p2Copy the code
Once again sweet by Kotlin!
Sixth Revision
Observant friends will notice that this extension operator returns a new object each time.
Is KTX a bad function?
That’s not the case. Now back to our fourth “optimization.”
Fun pointf.minusPoint (p2: PointF): PointF = this.apply {this.offset(-p2.x, -p2.y)}Copy the code
Now let’s consider a problem where we take p1 and subtract p2 to get an object P, where P is actually P1, and their properties have been changed. If p1 is then used to do some other operations, obviously the result is not the same as expected.
See what the problem is? Our optimization “subtraction” changes the minuend, which is obviously unreasonable.
So our fifth modification is not reasonable, but I do not want to use the sixth scheme, because it does have extra objects, I would starve to death, die outside, will not eat this grammar sugar? ! .
So what should be done?
We said that a subtraction should not change the minuend, and that the subtraction should be a new value.
So is that all we have to do? Of course not. Let’s go back to our requirement, “Get the difference between two points.” This requirement could have been modified a little bit more: “Get the difference between two points.
So here we see that we have a very suitable operator to describe it, which is -=
Go straight to the code
MinusAssign (p: PointF) {this.apply {offset(-p.x, -p.y)}} // Inline operator fun pointf.minusassign (p: PointF) {this.apply {offset(-p.x, -p.y)}} // Use, no return value p -= p2Copy the code
BTW, inline is redundant because the argument passed is not a function type.
Since there is no return value, we can call it this way
val p1 = p.apply {
this -= center
}
Copy the code
So we’re done subtracting.
What do I get by subtracting?
- You know kotlin’s operator notation
- You learned about some of Kotlin’s inline rules
- If a function modifies the parameters passed in, you need to be careful whether you really should do so.