- クラス継承をしないで機能拡張
Swift:
- Add computed properties and computed static properties
- Define instance methods and type methods
- Provide new initializers
- Define subscripts
- Define and use new nested types
- Make an existing type conform to a protocol
C#: Extension Methods
- インスタンスメソッドが追加される(ように見える)
Extension Syntax
Swift:
extension SomeType: SomeProtocol, AnotherProtocol {
// implementation of protocol requirements goes here
}
Computed Properties
- Double を拡張するプロパティ
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
9> 10.0.km
$R0: Double = 10000
Initializers
1> struct Size {
2. var width = 0.0, height = 0.0
3. }
4. struct Point {
5. var x = 0.0, y = 0.0
6. }
7. struct Rect {
8. var origin = Point()
9. var size = Size()
10. }
12> extension Rect {
13. init(center: Point, size: Size) {
14. let originX = center.x - (size.width / 2)
15. let originY = center.y - (size.height / 2)
16. self.init(origin: Point(x: originX, y: originY), size: size)
17. }
18. }
19> let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
20. size: Size(width: 3.0, height: 3.0))
centerRect: Rect = {
origin = {
x = 2.5
y = 2.5
}
size = {
width = 3
height = 3
}
}
Methods
1> extension Int {
2. func repetitions(task: () -> ()) {
3. for i in 0..<self {
4. task()
5. }
6. }
7. }
8> 3.repetitions({
9. println("Hello!")
10. })
Hello!
Hello!
Hello!
C#: Extension Methods
csharp> public static class Extensions {
> public static void Repeat(this int i , Action<int> act ){
> for(int x=0; x < i; x++ ) act(x);
> }
> }
csharp> 3.Repeat(delegate(int i){ Console.WriteLine(string.Format("{0} *** \n",i));});
0 ***
1 ***
2 ***
Mutating Instance Methods
- 破壊的
1> extension Int {
2. mutating func square() {
3. self = self * self
4. }
5. }
6> var someInt = 3
someInt: Int = 3
7> someInt.square()
8> someInt
$R0: Int = 9
Subscripts
1> extension Int {
2. subscript(var digitIndex: Int) -> Int {
3. var decimalBase = 1
4. while digitIndex > 0 {
5. decimalBase *= 10
6. --digitIndex
7. }
8. return (self / decimalBase) % 10
9. }
10. }
11> 746381295[0]
$R0: Int = 5
12> 746381295[1]
$R1: Int = 9
Nested Types
1> extension Int {
2. enum Kind {
3. case Negative, Zero, Positive
4. }
5. var kind: Kind {
6. switch self {
7. case 0:
8. return .Zero
9. case let x where x > 0:
10. return .Positive
11. default:
12. return .Negative
13. }
14. }
15. }
17> 3.kind
$R0: Int.Kind = Positive
18> (-1).kind
$R1: Int.Kind = Negative
19> 0.kind
$R2: Int.Kind = Zero
C# Dynamic Type
Dynamic is advanced functionality.
It can be useful.
But usually it should be avoided.
It erases many benefits of the C# language.
Dynamic Object
(StackOverFlow):
- Dictionaryのホルダーを内部に持って、System.Dynamic.DynamicObjectのメソッドのオーバーライドでごにょごにょする
using System.Dynamic;
class DynamicDuck : DynamicObject
{
Dictionary<string, object> dictionary
= new Dictionary<string, object>();
public int Count
{
get { return dictionary.Count; }
}
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
string name = binder.Name.ToLower();
return dictionary.TryGetValue(name, out result);
}
public override bool TrySetMember(
SetMemberBinder binder, object value)
{
dictionary[binder.Name.ToLower()] = value;
return true;
}
}
dynamic d = new DynamicDuck();
d.firstname = "Gideon";
d.Quack = (Action)(() => Console.WriteLine("Quack by " + d.firstname));
d.Quack();
Quack by Gideon