Why Do Self and Self Sometimes Refer to Different Types in Static Functions

When should I use 'self' over '$this'?

Short Answer

Use $this to refer to the current
object. Use self to refer to the
current class. In other words, use
$this->member for non-static members,
use self::$member for static members.

Full Answer

Here is an example of correct usage of $this and self for non-static and static member variables:

<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;

function __construct() {
echo $this->non_static_member . ' '
. self::$static_member;
}
}

new X();
?>

Here is an example of incorrect usage of $this and self for non-static and static member variables:

<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;

function __construct() {
echo self::$non_static_member . ' '
. $this->static_member;
}
}

new X();
?>

Here is an example of polymorphism with $this for member functions:

<?php
class X {
function foo() {
echo 'X::foo()';
}

function bar() {
$this->foo();
}
}

class Y extends X {
function foo() {
echo 'Y::foo()';
}
}

$x = new Y();
$x->bar();
?>

Here is an example of suppressing polymorphic behaviour by using self for member functions:

<?php
class X {
function foo() {
echo 'X::foo()';
}

function bar() {
self::foo();
}
}

class Y extends X {
function foo() {
echo 'Y::foo()';
}
}

$x = new Y();
$x->bar();
?>

The idea is that $this->foo() calls the foo() member function of whatever is the exact type of the current object. If the object is of type X, it thus calls X::foo(). If the object is of type Y, it calls Y::foo(). But with self::foo(), X::foo() is always called.

From http://www.phpbuilder.com/board/showthread.php?t=10354489:

By http://board.phpbuilder.com/member.php?145249-laserlight

compiler forcing self inside static method of a function while using dispatch_sync

The problem is not about dispatch_async, but it's because you are referencing self in a closure.

Whenever self is used in a closure, it is captured as a strong reference. That can potentially cause a strong reference cycle - to prevent that self is captured by mistake, swift requires that self is explicitly used when accessing properties and methods.

Note that self is defined in a static context, and refers to the type rather than an instance. So using self in a static method lets you access all static properties and methods defined in the same class/struct.

For more info, read Automatic Reference Counting

Calling a static method with self vs. class name

You make a few statements that aren't entirely correct:

Calling Python static methods using the class name is more common

It's not more common, it's the only way to do so from outside the class. i.e.:

class MyClass:
@staticmethod
def a_method():
pass


MyClass.a_method()

In this example, self.a_method() would not work, as self would not refer to an instance of MyClass.

calling a static method with self is the same as ClassName.static_method(self), where self would be ignored by the static method

That's not actually the case, for example:

class MyClass:
@staticmethod
def a_method():
pass

def another_method(self):
# this is fine
self.a_method()
# this causes an error, as .a_method expects no arguments
MyClass.a_method(self)

self simply refers to the instance of the class that called an instance method (which has the self argument, which doesn't even have to be called self - it's just whatever the first parameter is called, self is the convention.

You can call static methods on self, because self is an instance of the class that has the static method, and thus has the method. You can also call static methods on classes directly, because a static method doesn't require an object instance as a first argument - which is the point of the static method.

You're fine using self.a_method() where you like, just keep in mind that self will refer to an object of the class the object was instanced as, not the specific class you mention.

For example:

class ClassA:
@staticmethod
def a_method():
print('a')

def another_method(self):
# prints whatever a_method for the class of self prints
self.a_method()
# always prints 'a', as a_method for ClassA prints 'a'
ClassA.a_method()


class ClassB(ClassA):
@staticmethod
def a_method():
print('b')


a = ClassA()
a.another_method()
b = ClassB()
b.another_method()

The output:

a
a
b
a

So, you see, there is a difference between calling from self. and from Class.

reference the self type in a static method - C#

You can hide and so in a way override the getInstance method in the inheriting type like this:

class B : A {
public static new B getInstance() {
return new B();
}
}

The new keyword specifies that the hiding of the inherited method was intentional, otherwise you get a compiler warning.

Complete example:

using System;

class A {
public static A getInstance() { return new A(); }
public void PrintSelf() {Console.WriteLine(this.GetType().Name);}
}

class B : A {
public static new B getInstance() {
return new B();
}
}

public class MyClass {
public static void Main() {
A a = A.getInstance();
B b = B.getInstance();
a.PrintSelf();
b.PrintSelf();
}
}

What is the difference between self::$bar and static::$bar in PHP?

When you use self to refer to a class member, you're referring to the class within which you use the keyword. In this case, your Foo class defines a protected static property called $bar. When you use self in the Foo class to refer to the property, you're referencing the same class.

Therefore if you tried to use self::$bar elsewhere in your Foo class but you had a Bar class with a different value for the property, it would use Foo::$bar instead of Bar::$bar, which may not be what you intend:

class Foo
{
protected static $bar = 1234;
}

class Bar extends Foo
{
protected static $bar = 4321;
}

When you call a method via static, you're invoking a feature called late static bindings (introduced in PHP 5.3).

In the above scenario, using self will result in Foo::$bar(1234).
And using static will result in Bar::$bar (4321) because with static, the interpreter takes into account the redeclaration within the Bar class during runtime.

// self
var_dump(Foo::$bar);
// (int) 1234

// static
var_dump(Bar::$bar);
// (int) 4321

You typically use late static bindings for methods or even the class itself, rather than properties, as you don't often redeclare properties in subclasses; an example of using the static keyword for invoking a late-bound constructor can be found in this related question: New self vs. new static

However, that doesn't preclude using static with properties as well.

Swift - what's the difference between metatype .Type and .self?

Here is a quick example:

func printType<T>(of type: T.Type) {
// or you could do "\(T.self)" directly and
// replace `type` parameter with an underscore
print("\(type)")
}

printType(of: Int.self) // this should print Swift.Int


func printInstanceDescription<T>(of instance: T) {
print("\(instance)")
}

printInstanceDescription(of: 42) // this should print 42

Let's say that each entity is represented by two things:

  • Type: # entitiy name #

  • Metatype: # entity name # .Type

A metatype type refers to the type of any type, including class types, structure types, enumeration types, and protocol types.

Source.

You can quickly notice that this is recursive and there can by types like (((T.Type).Type).Type) and so on.

.Type returns an instance of a metatype.

There are two ways we can get an instance of a metatype:

  • Call .self on a concrete type like Int.self which will create a
    static metatype instance Int.Type.

  • Get the dynamic metatype instance from any instance through
    type(of: someInstance).

Dangerous area:

struct S {}
protocol P {}

print("\(type(of: S.self))") // S.Type
print("\(type(of: S.Type.self))") // S.Type.Type
print("\(type(of: P.self))") // P.Protocol
print("\(type(of: P.Type.self))") // P.Type.Protocol

.Protocol is yet another metatype which only exisits in context of protocols. That said, there is no way how we can express that we want only P.Type. This prevents all generic algorithms to work with protocol metatypes and can lead to runtime crashes.

For more curious people:

The type(of:) function is actually handled by the compiler because of the inconsistency .Protocol creates.

// This implementation is never used, since calls to `Swift.type(of:)` are
// resolved as a special case by the type checker.
public func type<T, Metatype>(of value: T) -> Metatype { ... }

How to use self parameter, @staticmethod keyword inside a class and its methods

Only use @staticmethod if you are creating a function that you'd normally want to tie to specific classes but do not need any other context. For example, the str.maketrans() function is a static method because it is a utility function you'd often use when working with strings, namespacing it to the already-existing str type (which pre-exists as a class) makes sense there.

You appear to be using classes as a namespace instead. Don't do that. Use a module for your functions, and you don't have to worry about the special scoping rules that apply to classes. Only use a class when you need to bundle state with functionality.

If you insist on using classes with static methods anyway, you are stuck with hardcoding the class name everywhere:

class myclass:
@staticmethod
def function1(param1)
print "function1"

@staticmethod
def main_function(param1)
# Want to use other functions in this class? Then you will
# have to use the full name of the class as a prefix:
myclass.function1(param1)

You could make use of classmethods instead so you have a reference to the class object:

class myclass:
@staticmethod
def function1(param1)
print "function1"

@classmethod
def main_function(cls, param1)
# Now you can use the `cls` reference to access other attributes
cls.function1(param1)

This has the added advantage that you can use inheritance.

However, using a module is the correct way to organise a set of functions into a namespace. Put everything into a my_module.py file in your package, and use importing;

import my_module

my_module.main_function(param1)

Now all globals in my_module are bundled into one module object, and no prefixing or cls references are needed.

Swift 3, is the .self in a metatype issue actually correct?

(Aside, NB, Swift3 needs the "!" on p.next: unfortunately I'm not sure exactly why.)

Because .next returns an Optional, but p is not optional. This will crash if you run out of responders.

1) It seems ... dangerous ... to change General to General.self - in fact is it safe and is the meaning the same as General in Swift <3 ?

I'm surprised that worked in earlier versions of Swift without the .self, but yes, .self is required in order to directly reference a metatype. Referencing metatypes is somewhat rare in Swift, and can lead to surprising behaviors if done unintentionally, so it requires an extra piece of syntax to say "yes, I really mean the type."

why is that a metatype? Did I "do something wrong" and make it ask for a metatype rather than just a type?

You did this correctly.

2) What the hell is a "metatype"?

The type of a type. An instance of a metatype is a type. Consider:

func f(x: Int)

To call this, you pass an instance of Int. So similarly:

func f<T>(x: T.Type)

To call this, you pass an instance of the metatype T.Type, which is a type.


Unrelated, but I would probably rethink this code along these lines. First, it is convenient to be able to treat the responder chain as a sequence. Here's one way to do that:

public extension UIResponder {
public func nextResponders() -> AnySequence<UIResponder> {
guard let first = next else { return AnySequence([]) }
return AnySequence(sequence(first: first, next: { $0.next }))
}
}

Then getting the next responder that matches a type is cleaner and clearer IMO (and works on any responder chain):

public extension UIResponder {
public func firstResponder<T: UIResponder>(ofType _: T.Type)-> T? {
return nextResponders()
.flatMap { $0 as? T }
.first
}
}

...

self.firstResponder(ofType: General.self)?.clickedHamburgerMenuButton()

Distinction in Swift between uppercase Self and lowercase self

Self refers to the type of the current "thing" inside of a protocol (whatever is conforming to the protocol). For an example of its use, see Protocol func returning Self.

The official docs I've found for Self is in Protocol Associated Type Declaration in The Swift Programming Language. It surprisingly is not documented in the sections on protocols or on nested types:

However, now there is a paragraph about Self Type including a code example in the official Swift Programming Language's chapter about Types



Related Topics



Leave a reply



Submit