I am having some problems in an exercise that I'm doing for the graphical interfaces course. I'm writing a program in F# defined in this way:
I have a class A, in which I override the method OnPaint;
I have another class B, in which I override the OnPaint method, OnMouse[Down/Move/Up] methods, etc.
I would use the overridden OnPaint method in A into the overridden OnPaint method defined in B (obviously, the OnPaint method in A, is defined in the class A, which means that I have to instantiate a type A object).
My question is: how can I do that? Do I need to define necessarily a method in A in which I pass a PaintEventArgs.Graphics parameter with the same tasks of the OnPaint method of A instead of override the OnPaint method in A?
An example:
I've to do something like this:
type Ellipse() =
...
override this.OnPaint e =
e.Graphics.DrawEllipse(10.f, 10.f, 30.f, 30.f)
type classThatUseEllipse() =
let ell = new Ellipse()
...
override this.OnPaint e =
ell.OnPaint(e)
Or something like this?:
type Ellipse() =
...
let myOnPaint (e:PaintEventArgs) =
e.Graphics.DrawEllipse(10.f, 10.f, 30.f, 30.f)
type classThatUseEllipse() =
let ell = new Ellipse()
...
override this.OnPaint e =
ell.myOnPaint(e)
Or these two versions are the same?
I'm asking this because often the first version gave problems.
Related
In a simple example like this, I can omit self for referencing backgroundLayer because it's unambiguous which backgroundLayer the backgroundColor is set on.
class SpecialView: UIView {
let backgroundLayer = CAShapeLayer()
init() {
backgroundLayer.backgroundColor = UIColor.greenColor().CGColor
}
}
But, just like in Objective-C, we can confuse things by adding local variables (or constants) named similarly. Now the backgroundColor is being set on the non-shape layer:
class SpecialView: UIView {
let backgroundLayer = CAShapeLayer()
init() {
var backgroundLayer = CALayer()
backgroundLayer.backgroundColor = UIColor.greenColor().CGColor
}
}
(this is resolved by using self.backgroundLayer.backgroundColor)
In Objective-C I always eschewed ivars for properties and properties were always prefixed with self for clarity. I don't have to worry about ivars in swift but are there other considerations for when I should use self in swift?
The only times self is required are when referencing a property inside a closure and, as you pointed out, to differentiate it from a local variable with the same name.
However, personally, I prefer to always write "self" because:
That is an instant and obvious sign that the variable is a property. This is important because it being a property means that its state can vary more widely and in different ways than a local variable. Also, changing a property has larger implications than changing a local variable.
The code does not need to be updated if you decide to introduce a parameter or variable with the same name as the property
Code can be easily copied in and out of closures that do require self
Most of the time we can skip self. when we access class properties.
However there is one time when we MUST use it: when we try to set self.property in a closure:
dispatch_async(dispatch_get_main_queue(), {
// we cannot assign to properties of self
self.view = nil
// but can access properties
someFunc(view)
})
one time when we SHOULD use it: so you don't mess a local variable with class property:
class MyClass {
var someVar: String = "class prop"
func setProperty(someVar:String = "method attribute") -> () {
print(self.someVar) // Output: class property
print(someVar) // Output: method attribute
}
}
other places where we CAN use self.
before property just to be expressive about were variable/constant comes from.
Looking at Ray Wenderlich's style guide
Use of Self
For conciseness, avoid using self since Swift does not require it to access an object's properties or invoke its methods.
Use self only when required by the compiler (in #escaping closures, or in initializers to disambiguate properties from arguments). In other words, if it compiles without self then omit it.
Swift documentation makes the same recommendation.
The self Property
Every instance of a type has an implicit property called self, which is exactly equivalent to the instance itself. You use the self property to refer to the current instance within its own instance methods.
The increment() method in the example above could have been written like this:
func increment() {
self.count += 1
}
In practice, you don’t need to write self in your code very often. If you don’t explicitly write self, Swift assumes that you are referring to a property or method of the current instance whenever you use a known property or method name within a method. This assumption is demonstrated by the use of count (rather than self.count) inside the three instance methods for Counter.
The main exception to this rule occurs when a parameter name for an instance method has the same name as a property of that instance. In this situation, the parameter name takes precedence, and it becomes necessary to refer to the property in a more qualified way. You use the self property to distinguish between the parameter name and the property name.
Here, self disambiguates between a method parameter called x and an instance property that is also called x:
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOf(x: Double) -> Bool {
return self.x > x
}
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
print("This point is to the right of the line where x == 1.0")
}
// Prints "This point is to the right of the line where x == 1.0"
I'm going to go against the flow and not use self unless absolutely required.
The reason why is that two of the main reasons to use self is
When capturing self in a block
When setting self as a delegate
In both cases, self will be captured as a strong reference. This might be what you want, but in many cases, you actually want to use a weak one.
Therefor, forcing the developer to use self as an exception and not a rule will make this strong capture more conscious, and let him reflect on this decision.
As Apple documentation says in https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
The self Property
Every instance of a type has an implicit property called self, which
is exactly equivalent to the instance itself. You use the self
property to refer to the current instance within its own instance
methods.
The increment() method in the example above could have been written
like this:
func increment() {
self.count += 1
}
In practice, you don’t need to write self in your code very often. If
you don’t explicitly write self, Swift assumes that you are referring
to a property or method of the current instance whenever you use a
known property or method name within a method. This assumption is
demonstrated by the use of count (rather than self.count) inside the
three instance methods for Counter.
The main exception to this rule occurs when a parameter name for an
instance method has the same name as a property of that instance. In
this situation, the parameter name takes precedence, and it becomes
necessary to refer to the property in a more qualified way. You use
the self property to distinguish between the parameter name and the
property name.
Here, self disambiguates between a method parameter called x and an
instance property that is also called x:
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOf(x: Double) -> Bool {
return self.x > x
}
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
print("This point is to the right of the line where x == 1.0")
}
// Prints "This point is to the right of the line where x == 1.0"
Without the self prefix, Swift would assume that both uses of x
referred to the method parameter called x.
I would prefer to keep using self whenever I'm using a property to omit these misunderstandings.
As Nick said, in objective-c we had ivars + synthesized properties which gave the _internal variable names to delineate things. Eg.
#IBOutlet (nonatomic,strong) UITableView *myTableView;
resulting in _myTableView to be (preferably) referenced internally - and self.myTableView to be reference beyond the class. While this is pretty black and white, consider the exception when programmatically instantiating views, you can gain clarity/ simplicity / reduce boilerplate by removing self.
#interface CustomVC:UIViewController
{
UITableView *myTableView;
}
In swift, the public / internal properties clarify this scope.
If it's a public property that other classes will interact with err on self.
Otherwise if it's internal skip self and avoid the automatic repetition.
The compiler will catch you when it's needed.
// UIViewcontroller swift header
public var title: String? // Localized title for use by a parent controller.
public var navigationItem: UINavigationItem { get }
/// In your class
self.title = "Clarity"
self.navigationItem.leftBarButtonItem = UIBarButtonItem()
// In superclass
#property(nonatomic, copy) NSString *screenName // use self.screenName in swift subclass
#IBOutlet myTableView:UITableView // use self
public var myTableView:UITableView // use self
internal var myTableView:UITableView // skip self
var myTableView:UITableView // skip self
I am using Realm and it has function that take as an argument a class inheriting from Object (not NSObject), e.g.
realm.objects(Class)
I want to make a function that also takes Class as parameter.
I want make function that will take a class and forward it to Realm's function. I tried something like this, but it doesn't work:
func test(type: AnyClass) {
let realm = ..
realm.objects(type)
}
The Swift compiler reports an error saying that it cannot cast from AnyClass to Object.Type
I found a similar question here: Pass a Swift class as parameter, and then call a class method out of it
But maybe there is a simpler solution that doesn't require protocol implementation for every class? I want the function to make the decision of what to do by itself depending on what class it receives.
I want it to look like realm.objects(Class).
You can use the same signature: objects declaration looks like this:
func objects<T: Object>(type: T.Type) -> Results<T>
So you need a generic function constraining the type to subclasses of Realm.Object:
func test<T: Object>(type: T.Type) {
let realm = ...
realm.objects(type)
}
Then, assuming that your class (MyClass in this sample) inherits from Realm.Object, you can call it like this:
class MyClass: Object {}
test(MyClass)
If your method takes an object of that type, you can infer the type:
func test<T: Object>(element: T) {
let realm = ...
realm.objects(T.self)
}
I am trying a bit of type (aka class) method but am confused on the real world application of such methods. e.g. In the following code from tutorialspoint.com -
class Math
{
class func abs(number: Int) -> Int
{
if number < 0
{
return (-number)
}
else
{
return number
}
}
}
let no = Math.abs(-35)
println(no)
So my question is that what is happening here when I am writing a type method. At what point of my programming may I need this. Can any one explain with a bit clear and simple example.
these kinds of functions are useful when you dont actually need an instance of the type to be made to be able to call it, eg helper methods. take the example you posted, if you call the abs function, you dont really need to make a Math object instantiated to do that (you could be seems unnecessary).
if your abs function wasnt a type method, you would have to go like this
var mathObject = Math()
mathObject.abs(-35)
as apposed to the way you have it in you example
Math.abs(-35)
both statements achieve the same goal, but the 2nd is more elegant (and memory efficient).
there are other reasons as well for using type methods, but this is just the simplest example of one (look up what a singleton is, for another example)
class C {
class func foo(){}
// Type method is always static !!!
static func boo() {}
}
class D: C {
override class func foo() {}
// this is not possible for 'Type method'
override static func boo() {} // error !!!!
}
In the following, the way I define Animator is common in OOP systems, where it is considered fine to mutate this object's state:
type MyViewController() =
inherit UIViewController()
//Is there a better way than this?
member val Animator = null with get, set
override this.ViewDidLoad() =
base.ViewDidLoad()
//this.View is defined in base class and is only valid *now*
this.Animator <- new UIDynamicAnimator(this.View)
Is there a more idiomatic way to define Animator that communicates: "null->object is ok, object -> object is forbidden"?
(Obviously, I could write a custom set function that checks and throws at runtime, but that seems more annoyingly "clever" than helpful.)
Once the library depends so heavily on inheritance, it is really hard to avoid the usual OO patterns, even when you're using F#. So to be fair, I would probably write exactly the same code you did and just live with the fact that this part of the code is not going to be that pretty (and use more functional approach in the parts of the application where you're not forced into OO style by the framework).
Also, in this case, I'd just live with the null - you can use option, but you're not getting any benefits, because you cannot do much if the value is None anyway.
Presumably, in your full source code, you are overriding other methods of the class and you are creating Animator so that it can be used in the other methods. One thing you could do is to extract the code from the class and write something like this:
type IInitializedView =
abstract OtherMethod : UIViewController -> unit
type MyViewController(viewInitialized:UIView -> IInitializedView) =
inherit UIViewController()
let mutable initializedView = None
override this.ViewDidLoad() =
base.ViewDidLoad()
initializedView := Some(viewInitialized this.View)
override this.OtherMethod() =
viewInitialized |> Option.iter (fun vi ->
vi.OtherMethod() )
The idea here is that MyViewController calls your function when it has view and your function then creates a new interface that handles the other method - but your interface is created only after everything is properly initialized!
let vc = MyViewController(fun view ->
// Now we have valid 'view' so we construct animator!
let animator = UIDynamicAnimator(view)
{ new IInitializedView with
member x.OtherMethod() =
// no problem here, because we have animator...
animator.Whatever() })
But I don't know enough about Xamarin to say whether this would work OK in a full more complex system.
I think what #Carsten gets at is that you shouldn't introduce null values unless you are absolutely forced to by interop with other CLI languages. Types declared in F# wouldn't allow them anyway, unless decorated with an AllowNullLiteralAttribute.
The value wrapped in the Option<'a> type would be a somewhat direct translation, but still has mutability. I'm assuming that you do not really need the property setter, replacing the automatic property with a let-bound value.
type MyViewController() =
inherit UIViewController()
let mutable animator = Option<UIDynamicAnimator>.None
member x.Animator = animator.Value
override this.ViewDidLoad() =
base.ViewDidLoad()
animator <- Some <| new UIDynamicAnimator(this.View)
On the other hand, wrapping in Lazy<'a> is a little bit more in the functional spirit.
type MyViewController() as this =
inherit UIViewController()
let animator = lazy(new UIDynamicAnimator(this.View))
member x.Animator = animator.Value
override this.ViewDidLoad() =
base.ViewDidLoad()
// Optional; only if you need the object creation right now
animator.Force() |> ignore
Is there a difference between these two function declarations?
func doSomething<T: UIViewController>(controller: T) {...}
vs.
func doSomething(controller: UIViewController) {...}
In Type Constraint Syntax section of the Apples Swift programming language book, there's this code sample:
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// function body goes here
}
with this description:
The hypothetical function above has two type parameters. The first type parameter, T, has a type constraint that requires T to be a subclass of SomeClass. ...
So in which cases is it better to use generic function described above?
They are different, but in the way you are using them, they amount to pretty much exactly the same result.
The difference is that when you call the generic version, the compiler sets T statically to be whatever type is passed in as the argument. When calling methods on that argument, this makes almost no difference – either way the calls on its methods will be dynamically dispatched, and you can't touch any parts of T that aren't guaranteed to be available from the constraint.
But suppose you made a change to this method to not just take an argument, but also return one, of the same type:
// T here will take the type of whatever is going in/out of the function
// be that UIViewController or a subtype of it
func doSomethingGenerically<T: UIViewController>(controller: T) -> T {
// some logic that results in a new controller being returned
}
// here the return type is fixed to be UIViewController
func doSomethingViaBaseClass(controller: UIViewController) -> UIViewController {
// some logic that results in a new controller being returned
}
Now, suppose you had a subclass of UIViewController that you were passing in, like so:
let subClass: MyUIViewController = ...
let controller1 = doSomethingGenerically(subClass)
let controller2 = doSomethingViaBaseClass(subClass)
Here, the type of the variable controller1 will be MyUIViewController, because that is what was passed in to the function so that is what T is. But the type of the variable controller2 will be UIViewController because that is the fixed type that doSomethingViaBaseClass returns.
Note, this doesn't mean the object they reference will be different - that depends on what the body of the function implements. It's just the type of the variables referring to it that will change.
There are other subtle differences but this is the main one to know about. In the case of structs, however, there are more differences worth noting. As it happens I wrote an article about them yesterday that might help.