21 Haziran 2017 Çarşamba

Interface

Interface Ne İçerebilir
C# arayüzlerinde property alanları olabilir.
An interface defines a contract that can be implemented by classes and structs. An interface can contain methods, properties, events, and indexers. An interface does not provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface.
Şöyle yaparız.
public interface IFoo
{
  string To {get; set;}
  ...
}
Tüm Property'ler ister istemez virtual tanımlıdır. Şu kod ile görebiliriz.
class Program
{
  public interface IWhatever
  {
    long? Id { get; set; }
  }

  public class Whatever : IWhatever
  {
    public long? Id { get; set; }
  }

  static void Main(string[] args)
  {
    var properties = typeof(Whatever)
      .GetProperties()
      .Where(_ => !_.GetMethod.IsVirtual)
      .Where(_ => !_.SetMethod.IsVirtual)
      .Select(_ => _.Name)
      .ToArray();

      Console.WriteLine(string.Join(", ", properties));
  }
}
Interface ve Kalıtım
Şöyle yaparız.
public interface IFoo
{
}
public interface IBar : IFoo
{
}
İstersek çoklu arayüz kalıtımı da yapabiliriz. Gerçek .Net kodunda da bu tür örnekler mevcut.
public interface ICollection<T> : IEnumerable<T>, IEnumerable
Nested Interface
Elimizde Athena isimli nested interface olsun.
public class Place {
  public interface Athena { }
}

public class Sparta : Place
{
  public void printTypeOfThis()
  {
    Console.WriteLine (this.GetType().Name);
  }

  public void printTypeOfSparta()
  {
    Console.WriteLine (typeof(Sparta));
  }

  public void printTypeOfAthena()
  {
    Console.WriteLine (typeof(Athena));
  }
}
Sparta nesnesi yaratır ve metodlarını çağırırız.
Sparta s = new Sparta();
s.printTypeOfThis();
s.printTypeOfSparta();
s.printTypeOfAthena();
Çıktı olarak şunu alırız. Nested Interface kendisini sarmayalan sınıf ismini de verir.
Sparta
Athena
Place+Athena
Şu kod true döner.
public class Sparta : Place
{
  public bool MakeItReturnFalse()
  {
    return this is Sparta;
  }
}
Eğer Sparta isimli sınıfın yanın yine aynı isimli nested bir interface eklersek
public class Place {
  public interface Athena { }
  public interface Sparta { } 
}
Bu sefer çıktı olarak şunu alırız.
Sparta
Place+Sparta
Place+Athena
Bu sefer şu kod false dönmeye başlar.
public class Sparta : Place
{
  public bool MakeItReturnFalse()
  {
    return this is Sparta;
  }
}
Sebebi ise uzun karmaşık. En basit açıklama şöyle
C# chooses to prioritize interfaces defined in the superclass in the name resolution

Interface ve Default Değerler
Arayüzde default değeler tanımlamak kodu okunaksız hale getiriyor. Kesinlikle kullanılmamalı ancak not almak istedim. Default değeler tanımlayan bir arayüzümüz olsun.
public interface IMovable
{
  void Move(int direction = 90, int speed = 100);
}
Default değerleri tekrarlamak istemezsek şöyle yapabiliriz. Buna explicit implementation deniyor.
public class Ball : IMovable
{
  //this uses the interface defaults
  //notice how you dont need to define the default values again
  //they are only specified once, in the interface definition
  void IMovable.Move(int direction, int speed)
  {
    Debug.WriteLine(direction + "," + speed);
  }

  //now for the specific case of this class you can have your own defaults
  //or none, just what ever fits your needs
  public void Move(int direction = 20, int speed = 10)
  {
    Debug.WriteLine(direction + ","+ speed);
  }

  public void Play()
  {
    Debug.WriteLine("From interface");
    ((IMovable) this).Move();
    Debug.WriteLine("From this class defaults");
    Move();
   }
}
Çıktı olarak şunu alırız.
From Interface
90, 100
From this class defaults
20, 10
İkinci Move metodunu yazmasaydık bile kendi nesnemizi arayüz tipine cast ederek metodumuzun default değerler ile çağrılmasını sağlarız.
((IMovable)this).Move();



Hiç yorum yok:

Yorum Gönder