I'm just taking my first steps with Swift and after having worked with things like PHP, Ruby, JavaScript and Python, this is all totally new to me.
So, I have code like this:
class DerpController: NSURLConnectionDelegate, NSURLConnectionDataDelegate {
func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse) {
println("response received")
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
println("data received")
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
println("request finished")
}
}
What are these things called: didReceiveResponse, didReceiveData? Are they some kind kind of message identifier or what?
And is func connection one overloaded method or are there actually two that are identified by these "didReceive..." names?
didReceiveResponse is an external parameter name. response and data are local parameter names.
This means that the first function is called with myDerpController.connection(url, didReceiveResponse:response). But within the body of the function you refer to the parameter as response.
The second function is a typo, and should be didReceiveData
These are delegate methods defined by NSURLConnectionDataDelegate, which is a protocol you have adopted.
In Swift, a parameter can have both an internal (parameter, local) name and an external (argument, caller) name. The internal name (response:, data:) is entirely up to you; the name provided by the docs and by code completion is just a "serving suggestion". The external name, however, needs to match the selector name by which Objective-C (or any other caller) will seek it. The method is called e.g. connection:didReceiveData: so you must use an external name didReceiveData for the second parameter in order to be called.
You also asked (irrelevantly) about overloading. Overloading by type is legal in Swift but not in Objective-C; the latter uses names (selectors) alone. You're biting off a lot at once here because you've chosen to start with an example involving heavy interplay between Swift and Objective-C, to understand which you really need to know at least the rudiments of both languages.
Related
var response Response
switch wrapper.Domain {
case "":
response = new(TypeA)
case "TypeB":
response = new(TypeB)
case "TypeC":
response = new(TypeC)
case "TypeD":
response = new(TypeD)
}
_ = decoder.Decode(response)
As shown in the code snippet, I got enough information from the Domain filed of wrapper to determine the type of response, and for each type, the following operations are performed:
create a new instance of that type using new
use the decoder to decode the byte slice to the instance created in step 1
I am wondering if there is a way to make the first step more generic and get rid of the switch statement.
A bit about your code
As per discussion in comments, I would like to share some experience.
I do not see nothing bad in your solution, but there are few options to improve it, depends what you want to do.
Your code looks like classic Factory. The Factory is a pattern, that create object of a single family, based on some input parameters.
In Golang this is commonly used in simpler way as a Factory Method, sometimes called Factory function.
Example:
type Vehicle interface {};
type Car struct {}
func NewCar() Vehicle {
return &Car{}
}
But you can easily expand it to do something like you:
package main
import (
"fmt"
"strings"
)
type Vehicle interface {}
type Car struct {}
type Bike struct {}
type Motorbike struct {}
// NewDrivingLicenseCar returns a car for a user, to perform
// the driving license exam.
func NewDrivingLicenseCar(drivingLicense string) (Vehicle, error) {
switch strings.ToLower(drivingLicense) {
case "car":
return &Car{}, nil
case "motorbike":
return &Motorbike{}, nil
case "bike":
return &Bike{}, nil
default:
return nil, fmt.Errorf("Sorry, We are not allowed to make exam for your type of car: \"%s\"", drivingLicense)
}
}
func main() {
fmt.Println(NewDrivingLicenseCar("Car"))
fmt.Println(NewDrivingLicenseCar("Tank"))
}
Above code produces output:
&{} <nil>
<nil> Sorry, We are not allowed to make exam for your type of car: "Tank"
So probably you can improve your code by:
Closing into a single function, that takes a string and produces the Response object
Adding some validation and the error handling
Giving it some reasonable name.
There are few related patterns to the Factory, which can replace this pattern:
Chain of responsibility
Dispatcher
Visitor
Dependency injection
Reflection?
There is also comment from #icza about Reflection. I agree with him, this is used commonly, and We cannot avoid the reflection in our code, because sometimes things are so dynamic.
But in your scenario it is bad solution because:
You lose compile-time type checking
You have to modify code when you are adding new type, so why not to add new line in this Factory function?
You make your code slower(see references), it adds 50%-100% lose of performance.
You make your code so unreadable and complex
You have to add a much more error handling to cover not trivial errors from reflection.
Of course, you can add a lot of tests to cover a huge number of scenarios. You can support TypeA, TypeB, TypeC in your code and you can cover it with tests, but in production code sometime you can pass TypeXYZ and you will get runtime error if you do not catch it.
Conclusion
There is nothing bad with your switch/case scenario, probably this is the most readable and the easiest way to do what you want to do.
Reference
Factory method: https://www.sohamkamani.com/golang/2018-06-20-golang-factory-patterns/
Classic book about patterns in programming: Design Patterns: Elements of Reusable Object-Oriented Software, Erich Gamma and his band of four, ISBN: 978-0201633610
Reflection benchmarks: https://gist.github.com/crast/61779d00db7bfaa894c70d7693cee505
I have two golang functions, doing exactly same thing, one takes input a slice and the other takes a map as input. I want to combine this into one function, to avoid duplication.
func DoSomething([]data) {
//do something.
}
func DoSomething(map[string]data) {
//do something.
}
Combined function may look like:
func DoSomethingNew (param type) {
//param could be map or slice
}
I want to know if it is possible to pass different types to same function in golang and how. I googled but couldn't find anything relevant.
You can use interfaces Go Playground
func F(data interface{}) {
switch data.(type){
case []int:
fmt.Println("Slice")
fmt.Println(data)
case map[string]int:
fmt.Println("Map")
fmt.Println(data)
}
fmt.Println()
}
where you actually check for the type and do something based on the type.
There are several ways you could do this, but the simple way would be to make it so DoSomethingNew accepts the interface{} type. Inside of the method you would then do a type switch or in this case with only two options, perhaps just one type assertion, followed by the other, returning error if both fail. Another option would be to have both as arguments and check for nil inside the function with a similar if, else-if, else pattern to handle the error if the input is of neither types you're looking for. To make your code more safe you could move to a more strict interface than the empty one which all types implement. You could also do some method chaining or even implement the method with using the types themselves as the receiving type. Here's an example that shows a few of the ideas; https://play.golang.org/p/_v2AyFjGzv
I'm really struggling to find a name for a type of function I've come across.
Here is the function in question:
https://github.com/go-fsnotify/fsnotify/blob/master/fsnotify.go#L32
This is how I'm using it (as per the fsnotify example):
select {
case event := <-watcher.Events:
log.Println("Event Triggered: ", event)
In that Println 'event' is returning the formatted string as per the function above, I'm just struggling to understand how a straight call to 'event' is using that function yet I would be expecting it to be accessed like the struct fields (event.Name, event.Op):
event.funcForReturningNicelyFormattedEvent()
It feels like this is a 'default' function as it has no name and it just returns the formatted data - I'm struggling to come up with the name/type/search term so I can find out more and understand the concept and importantly the reasoning behind it better.
Any help is appreciated.
It's very simple - println uses the String() method on any struct that implements it automatically. This is a classic use case of Go's implicit interfaces: every struct that has the methods an interface includes, is considered to be implementing the interface.
If it has func String() string it is considered a Stringer and used by fmt. You can use it on your own structs too, of course.
Function Println checks if the passed value implements interface Stringer. If it does it calls method String on this value. Event type implements that interface by supplying its implementation of String method in the excerpt you linked to.
In Go you don't have to declare that you implement interface.
I have a strange issue (which I can overcome however I would like to get a proper understanding of my error).
I have a small random number generator function which I use often:
func ranNum(low: Int, high:Int) -> UInt32 {
var result = arc4random_uniform(UInt32((high+1)-low)) + low
return result
}
When I use this in XCode playgrounds it works just fine if I pass in something like:
ranNum(1, 10)
However, in a regular Swift file it generates the error message : Missing argument label 'hi:' in call. Now I can overcome this by calling the function this way:
ranNum(1, hi:10)
Apart from it just being a little harder to read, it just isn't making sense why it works in Playgrounds but also why it requires only the 2nd argument label and not both. Any help as to what I am not understandinh would be greatly appreciated.
That's called external parameter name, and by default:
global functions: don't have implicit external names
class/struct methods: external names are automatically defined for all parameters after the first
initializers: external names are automatically defined for all parameters
If not explicitly specified, external names take the same name as the local parameter.
You can override that by prefixing a local parameter name with _. In your case:
func ranNum(low: Int, _ high:Int) -> UInt32 {
...
}
You mentioned that in playground calling the function works without any external parameter name - I may argue that:
in playground you have that function as a global function
in other tests, that function is a class/struct method
Am I right?
This initialiser will cause an error complaining that "with" is implied for the first parameter of an initialiser; did you mean name?
init(withName: String){
}
I'm not sure what this means, if it provides automagically the withName external parameter name if I call it name or what...
If I change it to
init(name: String){
}
any attempt at calling it init(with: "joe") or init(withName: "Joe") will fail. So I have no idea what the error message is telling me and how I can declare it so I call it init(withName: "joe").
In Swift you should not add with to the initializer. The initializer should be init(name:) and you should call it as Object(name: "joe").
This is because of how Swift methods bridge to ObjC. In ObjC, that initializer will automatically be translated to initWithName:. If you named it init(withName:) it would become initWithWithName:.