- Computed Properties & Stored Properties
Stored Properties
Swift:
- Class & Strucutreに“所有される構成要素”
- variable stored properties(var)
- constant stored properties(let)
C#:
- Field (const, readonly...)
- Property
Stored Properties of Constant Structure Instances
Swift:
1> struct Point{ var x = 0 ; let y = 0 }
2> var p = Point()
p: Point = {
x = 0
y = 0
}
3> p.x = 10
4> p.y = 10
/var/folders/3n/0lk686q1129clzkw38blpwdc0000gp/T/lldb/66693/repl7.swift:2:5: error: cannot assign to 'y' in 'p'
p.y = 10
~~~ ^
C#: そもそも constはインスタンスではなくてクラスのスコープ
- struct はパラメータ初期化のコンストラクタを明示的に宣言する必要がある
csharp> public struct Point {
> public int x ;
> public const int y=0;
> public Point(int x ) { this.x = x ; } // 必須
> };
csharp> var p = new Point(0);
csharp> p.y
(1,4): error CS0176: Static member `Point.y' cannot be accessed with an instance reference, qualify it with a type name instead
csharp> Point.y
0
csharp> p.x = 10
csharp> p.x
10
Swift: structインスタンスをletで定数にできる
4> let pf = Point()
pf: Point = {
x = 0
y = 0
}
5> pf.x = 10
/var/folders/3n/0lk686q1129clzkw38blpwdc0000gp/T/lldb/66693/repl11.swift:2:6: error: cannot assign to 'x' in 'pf'
pf.x = 10
~~~~ ^
C#: structインスタンスをreadonlyで定数にできる
csharp> public class Container {
> public const Point Origin = new Point(0);
> }
(2,23): error CS0283: The type `Point' cannot be declared const
csharp> public class Container {
> public readonly Point Origin = new Point(0);
> }
csharp> var c = new Container();
csharp> c.Origin.x = 100;
(1,11): error CS1648: Members of readonly field `Container.Origin' cannot be modified (except in a constructor or a variable initializer)
csharp> var p2 = c.Origin;
csharp> p2.x = 100;
csharp> p2.x
100
Lazy Stored Properties
A lazy stored property is a property whose initial value is not calculated until the first time it is used.
You indicate a lazy stored property by writing the lazy modifier before its declaration.
Swift:
6> class Container {
7. lazy var position = Point()
8. }
9> var c = Container()
c: Container = {
position.storage = nil
}
10> c.position.x
$R0: Int = 0
11> c
$R1: Container = {
position.storage = (x = 0, y = 0)
}
C#: Propertyを使う
public class Point
{
public int x;
public const int y = 0;
}
public class Container {
public Point _pos=null;
public Point Position {
get {
this._pos = this._pos ?? new Point();
return this._pos;
}
}
}
var c = new Container();
Assert(c._pos == null );
Assert(c.Position.x == 0 );
Assert(c._pos != null );
Stored Properties and Instance Variables
Objective-Cでの値の持ち方
- プロパティ
- インスタンス変数をバッキングストアとして使う
Swiftはプロパティのみ
よくわかっていません。 Computed Propertiesで get/setすればよいということではないのかな?
Computed Properties
Swift:
struct Point { var x = 0.0, y = 0.0 }
struct Size { var width = 0.0, height = 0.0 }
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
return Point(
x: origin.x + (size.width / 2) ,
y: origin.y + (size.height / 2)
)
}
set(value) {
origin.x = value.x - (size.width / 2)
origin.y = value.y - (size.height / 2)
}
}
}
var square = Rect(
origin: Point(x: 0.0, y: 0.0),
size: Size(width: 10.0, height: 10.0))
let p1 = square.center
square.center = Point(x: 15.0, y: 15.0)
assert(p1.x != square.center.x)
C#
public struct Point {
public double x = 0.0; public double y = 0.0 ;
public Point(double x, double y)
{ this.x = x; this.y = y; }
}
public struct Size {
public double width = 0.0f; public double height = 0.0f ;
public Size(double w, double h)
{ this.width = w; this.height=h;}
}
public struct Rect
{
public Point origin;
public Size size;
public Point Center
{
get {
return new Point(
origin.x + (size.width / 2) ,
origin.y + (size.height / 2)
);
}
set{
origin.x = value.x - (size.width / 2.0);
origin.y = value.y - (size.height / 2.0);
}
}
public Rect(Point p, Size s )
{
this.origin =p ; this.size =s ;
}
}
var square = new Rect(
new Point(0.0f, 0.0f),
new Size(10.0f, 10.0f));
var p1 = square.Center;
square.Center = new Point(15.0, 15.0);
Console.WriteLine(p1.x == square.Center.x);
False
Shorthand Setter Declaration
Swift: newValue
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
C# : value
set {
origin.x = value.x - (size.width / 2)
origin.y = value.y - (size.height / 2)
}
Read-Only Computed Properties
Swift: setがなければ getの修飾も省略できる
var readonly_center : Point {
return center
}
assert(square.center.x == square.readonly_center.x )
C#: getは省略できない
Property Observers
オブザーバー:
- willSet is called just before the value is stored.
- didSet is called immediately after the new value is stored.
1> struct Point {
2. var x: Int = 0 {
3. willSet(val){ println("setting \(val) to x")}
4. didSet{ println("x is now \(x)")}
5. }
6. }
7> var p = Point(x:0)
p: Point = {
x = 0
}
8> p.x = 10
setting 10 to x
x is now 10
C# : set の中でやる
set {
// do will set
_x = value;
// do did set
}
C# 6.0: プロパティに初期値をセットできるので
public int X { get;set; } = x;
public int Y { get;set; } = y;
Global and Local Variables
Swift: グローバル変数でもいろいろできる
オブザーバー:
1> var x: Int = 0 { didSet{ println("set to \(x)")} }
x: Int = 0
2> x = 3
set to 3
get/set: うれしいのだろうか。。。
1> var x : Int = 0;
x: Int = 0
2> var y : Int { get{ return 2*x } set { x = 2*newValue }}
y: Int = <computed property>
3> y
$R0: Int = 0
4> x = 1
5> y
$R1: Int = 2
6> y = 3
7> x
$R2: Int = 6
8> y
$R3: Int = 12
C#: 変数はどこかクラスにあって static フィールドにも get/set できる
Type Properties
C#: Static Property
Type Property Syntax / Querying and Setting Type Properties
Swift : struct, enum <- static, class <- class
19> struct Point {
20. var x = 0
21. var y = 0
22. static var shared = 0
23. static let origin = 0
24. }
26> var p1 = Point(x:10, y:10)
p1: Point = {
x = 10
y = 10
shared = 140461199908160
origin = 140461199915776
28> var p2 = Point(x:100, y:100)
p2: Point = {
x = 100
y = 100
shared = 7365411997647719716
origin = 3547200665735411558
}
29> Point.shared = 3
30> Point.shared
$R1: Int = 3
31> Point.origin
$R2: Int = 0
33> Point.origin = 3
/var/folders/3n/0lk686q1129clzkw38blpwdc0000gp/T/lldb/71998/repl37.swift:2:14: error: cannot assign to the result of this expression
Point.origin = 3
~~~~~~~~~~~~ ^
- error: class variables not yet supported
2> class Point {
3. var x = 0
4. var y = 0
5. class var origin = (0, 0)
6. }
/var/folders/3n/0lk686q1129clzkw38blpwdc0000gp/T/lldb/86707/repl8.swift:5:5: error: class variables not yet supported
class var origin = (0, 0)
^~~~~
- 別途ストレージを用意(グローバルとか)
15> var global_origin = (0, 0)
global_origin: (Int, Int) = {
0 = 0
1 = 0
}
24> class Point {
25. var x = 0
26. var y = 0
27. class var origin :(Int, Int) {
28. get{ return global_origin}
29. set { global_origin = newValue }
30. }
31. }
50> Point.origin = (100, 100)
51.
51> Point.origin
$R4: (Int, Int) = {
0 = 100
1 = 100
}
- structはstatic OK
1> struct Point {
2. static var count = 0
3. var x: Int = 0 {
4. didSet { Point.count++ }
5. }
6. }
7> var p1 = Point(x:0)
p1: Point = {
count = 0
x = -3458755736018865426
}
8> var p2 = Point(x:0)
9.
p2: Point = {
count = 0
x = 8070459310046764983
}
9> p1.x = 10
10> p2.x = 20
11> Point.count
$R0: Int = 2
- C#
csharp> public class Point {
> public static int Count = 0;
> protected int _x = 0;
> public int X {
> get { return _x; }
> set { _x = value; Count++; }
> }
> }
csharp> var p1 = new Point();
csharp> var p2 = new Point();
csharp> p1.X = 10;
csharp> p2.X = 20;
csharp> p2.X == p1.X * 2
true
csharp> Point.Count
2