20 Mayıs 2016 Cuma

-C++ Tür Dönüştürme(Casting)-

Merhabalar,
Bu yazıda C++'da tür dönüştürme işleçlerini inceleyeceğiz. Fakat tür dönüştürmenin ne olduğu ile ilgili
temel bilgi verilmeyecektir.

C++'da beş adet tür dönüştürme işleçi vardır.Bunlar:
- Standart C'den kalan yöntem.
- static_cast
- const_cast
- dynamic_cast
- reinterpret_cast

Tür dönüştürme işlemlerine standart C yöntemiyle başlayacağız. Ancak C++ derleyicileri ayrıca otomatik olarak tür dönüştürme işlemleri gerçekleştirir. Dolayısıyla derleyiciye göre C++'de tür dönüştürme işleçleri,yukarıda yer verilen sayıdan farklılık gösterebilir. Derleyicinin sahip olduğu işleçlere değinilmeyecektir.

Standart C'den kalan yöntemin kullanımına aşağıda yer verilmiştir:

int sayi = 10.0;
double d = (double) sayi;

Standart yöntem gayet sade bir yapıya sahiptir. Ancak bu yöntemin kullanılması önerilmez.
Çünkü C++ derleyicisi bu kullanımda programcıya hiçbir şekilde katkı sağlamaz.
Dolayısıyla hatalı kullanım ve/veya uyarı durumlarda derleyici sessiz kalacaktır.

C++'da tür dönüştürme işlemi daha detaylı bir yapıya sahiptir. Yani birçok amaca uygun tür dönüştürme yöntemleri mevcuttur.

-static_cast:
Bu yöntem,isminden de anlaşıldığı gibi dinamik sözkonusu olmayan durumlarda kullanılır. Yani çalışma zamanı esnasında,dönüştürme işlemine tabi tutulan tür'den emin olmayı gerektirir.
Dolayısıyla derleme zamanında bilinen tür dönüşümlerde bu yapı kullanılabilir.
static_cast kullanımını gösteren bir uygulamaya aşağıda yer verilmiştir.
Örnek:
#include <iostream>
#include <typeinfo>

using namespace std;

class Model
{
public:
Model()
{
//
}
~Model()
{//...
}

};

class BMW : public Model
{
public:
void modelIsmi()
{
cout << "BMW" << endl;
}

};

class Mercedes : public Model
{
public:
  void modelIsmi()
{
cout << "Mercedes" << endl;
}
};

int main()
{
  Model *model1 = new Model();
  Model *model2 = new Model();
  
  BMW *model3 = static_cast<BMW*>(model1);
  model3->modelIsmi();
  
  Mercedes *model4 = static_cast<Mercedes*>(model2);
  model4->modelIsmi();

 return 0;
}



-const_cast:
const olarak tanımlanmış bir değişken,const olarak tanımlanmamış bir başka değişkene atanamaz.
Dolayısıyla aşağıda verilen örnekte hata meydana gelecektir.
Örnek:
const char* text = "Kerim FIRAT";
char *veri2 = text;

Ancak "const" tanımlı bir türü manipüle etmek için "const_cast" tür dönüştürme yapısı kullanılabilir.
Yani bu yapı "const" olarak tanımlanmış türler üzerinden kullanılır.
Aşağıda bu örneğe yer verilmiştir.
Örnek:

const char *text = "Kerim FIRAT";
char *text2 = const_cast<char*>(text);
cout << text2 << endl;



-dynamic_cast:
Bu dönüştürme yöntemi referans ve göstericiler(pointer) de kullanılır.
Dönüştürme işlemi başarısız olması durumunda geri dönüş değeri "NULL" olur.
Ayrıca üst sınıfta enaz bir adet "virtual" fonksiyon bulundurmak zorunludur.
Örnek:
using namespace std;

class Model
{
public:
Model()
{
//
}
virtual void modelIsmi()
{
}

~Model()
{//...
}
 };

class BMW : public Model
{
public:
virtual void modelIsmi()
{
cout << "BMW" << endl;
}

};

class Mercedes : public Model
{
public:
  virtual void modelIsmi()
{
cout << "Mercedes" << endl;
}
};

int main()
{

  Model *model1 = new Model();
  Model *model2 = new Mercedes();

  Model *model3;
  
  model3 = dynamic_cast<BMW*>(model1);
  if(model3 !=NULL)
  {
model3->modelIsmi();
  }else{
cout << "model3 BMW'ye dönüştürme hatalı.!" << endl;
  }

  model3 = dynamic_cast<Mercedes*>(model2);
  if(model3 !=NULL)
  {
 model3->modelIsmi();
  }else{
 cout << "model3 Mercedes'ye dönüştürme hatalı.!" << endl;
  }
   
 return 0;
}

Çıktı:
model3 BMW'ye dönüştürme hatalı.!
Mercedes


-reinterpret_cast:
Tür dönüştürme yapılarında en esnek çalışan yapı budur.
Bu yapıyla,her türden gösterici(pointer)'i her türlü gösterici türüne çevirebiliriz.
Bukadar esnek olmasındaki sebep ise aslında bit taşıyor olmasından kaynaklanıyor.
Yani dönüştürülecek nesnenin bit yapısını diğer nesneye kopyalar. 
Ancak kullanırken dikkatli olmalısınız. Esnek olması tüm türleri hatasız dönüştürecek diye bir anlam oluşturmaz.
Kullanım örneğine aşağıda yer verilmiştir.

int main()
{
int sayi = 44;
unsigned int *unsint = reinterpret_cast<unsigned int*>(&sayi);
cout << *unsint << endl;

    Model *model1 = new Model();
    Model *model2 = new Mercedes();
    
     BMW *model3;
     model3 = reinterpret_cast<BMW*>(model1);
     model3->modelIsmi();
     
     Mercedes *model4;
     model4 = reinterpret_cast<Mercedes*>(model2);
     model4->modelIsmi();
  return 0;
}

İyi çalışmalar..

15 Mayıs 2016 Pazar

-Java Properties Kullanımı-


Merhabalar,
Java uygulamaları geliştirirken,uygulama ile ilgili birtakım ayarlar belirleyip bu ayarları uygulamamızda varsayılan(default) ayarlar olarak kullanmamız gerekebilir.
Böyle bir durumda Java'nın "properties" özelliğini kullanabiliriz. Bu özellik bir dosya üzerinden çalışır.
Belirlediğimiz bilgileri "config.properties" isimli(isim belirleme geliştiricinin insiyatifindedir) bir dosyaya kaydedebilir,gerektiği durumda bu dosya içeriğini okuyarak bilgileri kullanabiliriz.
Aslında standart dosya işlemine benzerlik gösterir. Fakat Java'da bu işlemler için belirli yardımcı Class'lar mevcuttur.
Ancak başlıca kullanacağımız Class "Properties" dir.

Properties Class'ı "java.util" paketi altında bulunur. Bu Class "Hashtable<Object,Object>" Class'dan extends edilmiştir. 
Dolayısıyla "Hashtable"'nin belli özelliklere göre düzenlenmiş halidir. Ayrıca dosya işlemleri ile ilgili birtakım işlemler için iç Class barındırır.
Örneğin config içeriği okumayla ilgili esnek yapılar,convert(hex,..) ve Xml desteği vb. gibi..
Ancak bu makalede sadece standart kullanımı işlenmiştir.
Properties Class ile ilgili daha geniş bilgi için makale sonunda verilen linki inceleyebilirsiniz.

Properties kullanımını gösteren Java uygulamasına aşağıda yer verilmiştir. Verilen uygulamada iki adet Class kullanılmıştır.
Main.java Classı uygulamanın Main kısmını içerir. Config dosyasına aktarmak istediğimiz veriler burada belirlenmiştir.
İkinci Class ise MyPropertiesClass.java dır. Bu Class içersinde Properties işlemleri yer almaktadır.
Kod satırlarında gerek görülen yerlere yorum yazılmıştır.

Main.java:
import java.io.IOException;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
/*
* Config dosyasına kaydetmek istediğimiz verileri "key,value"
* şeklinde TreeMap içersine eklenmiştir.
*/
TreeMap<String, String> treeMap = new TreeMap<String, String>();
treeMap.put("username", "kerim");
treeMap.put("password", "1234");
treeMap.put("screenSize", "1280x720");
treeMap.put("sound", "music.mp4");
 
  
try {
//TreeMap ile belirlenen içerikler Properties için MyPropertiesClass'a gönderiliyor:
MyPropertiesClass.wirteProperties(treeMap);

//Config dosyası içeriği "key,value" şeklinde alınıyor ve ekrana yazdırılıyor:
TreeMap<String, String> treeMapRead = MyPropertiesClass.readProperties();
for(String key: treeMapRead.keySet()){
System.out.println(key+ "=" + treeMapRead.get(key));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

MyPropertiesClass.java:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Properties;
import java.util.TreeMap;

public class MyPropertiesClass {

//Ayarları kaydedeceğimiz config dosyası ismi belirtiliyor. İsim belirleme geliştirici insiyatifindedir.
private static String PROPERTIES_FILE = "config.properties";
    /*kaydedilecek ayarların key değerleri tutuluyor.
     * NOT:bu yöntem geçici olarak çalışır. uygulama kapatıldığında içeriğini kaybeder.
     * Dolayısıyla uygulama için belirlediğiniz config key değerleri kalıcı olarak tutulmalıdır.
     */
private static ArrayList<String> propertiesKey = new ArrayList<String>();
public MyPropertiesClass(){
///
}

//Main.java tarafından TreeMap olarak gelen "key,value" değerleri config dosyasına yazacak fonksiyonumuz:
public static void  wirteProperties(TreeMap<String, String> _treeMap) throws IOException{
//Properties nesnesi oluşturuluyor:
Properties properties = new Properties();
//Config dosyasına yazma işlemi için File nesnesi oluşturuluyor:
OutputStream outStream = new FileOutputStream(PROPERTIES_FILE);
//döngü vasıtasıyla TreeMap içeriği okunuyor:
for(String key : _treeMap.keySet()){
//config key'leri okuma işleminde kullanmak için tutuyorum.
propertiesKey.add(key);
//Config için belirlenen her "key,value" tek tek setProperty fonksiyonuna gönderiliyor:
properties.setProperty(key, _treeMap.get(key));
}
/*tüm config ayarları aktarıldıktan sonra yazma işlemi için "store" fonksiyonu çağrılıyor:
* store fonksiyonu ikinci parametre olarak comments değerini alır.Yani config dosyası ile ilgili bir girdi belirlenebilir.
* istenmediği durumda null değeri verebilirsiniz.
*/
properties.store(outStream, "ayarlar");
   //config dosyası kapatma işlemi:
if(outStream !=null){
outStream.close();
}

}

//Config dosya içeriğini okumak için çağırdığımız fonksiyon:
public static TreeMap<String,String> readProperties() throws IOException{
//Properties nesnesi oluşturuluyor:
Properties properties = new Properties();
//Config dosyasını okumak için File nesnesi oluşturuluyor:
InputStream inputStream = new FileInputStream(PROPERTIES_FILE);

//Config içeriği properties nesnesine yükleniyor:
properties.load(inputStream);

//Main.java tarafına göndermek için TreeMap oluşturuyoruz:
TreeMap<String, String> treeMap = new TreeMap<String, String>();
//Daha önce sakladığım config key'leri ile döngü oluşturuyoruz:
int size = propertiesKey.size();
    for(int i=0;i<=size - 1;i++ ){
    //getProperty fonksiyonu ile key değeri verilen config ayarları okunuyor:
treeMap.put(propertiesKey.get(i), properties.getProperty(propertiesKey.get(i)));
}

return treeMap;
}
}

Oluşturulan "config.properties" dosyası java projenize ait dizinde yer alır.
Config Dosya içeriği:

#ayarlar
#Sun May 15 19:09:02 GMT-12:00 2016
sound=music.mp4
username=kerim
screenSize=1280x720
password=1234

Program çıktısı:
password=1234
screenSize=1280x720
sound=music.mp4
username=kerim

Detaylı bilgi için:
https://docs.oracle.com/javase/tutorial/essential/environment/properties.html
https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html

İyi çalışmalar.

7 Mayıs 2016 Cumartesi

-Java Reflection Kullanımı -

Merhabalar,
Android Framework API geliştirirken,cihazın SIM kartları ile ilgili birtakım bilgileri kullanmam gerekiyordu.
Bu bilgilerin bulunduğu Java sınıfları(class) farklı dizinde ve paket içersinde bulunuyordu. 
İlgili class'lara Reflection(yansıtma) ile erişmeyi ve gerekli fonksiyon ve parametreleri kullandım.

Reflection; Java sınıflarına(class) erişim ve içeriğini kullanabilmek için geliştirilmiş bir kütüphanedir.
Reflection kütüphanesi 'java.lang.reflect' paketi altında bulunur. Bu paket altında bulunan Interface,Class ve Exception kalıplarıyla
Class'lar üzerinde esnek işlemler uygulamak mümkündür. Ancak bu makalede tüm 'java.lang.reflect' paket içeriğini değil,sadece 'Method' Class içersinde birkaç özellik kullanacağız.
İlk olarak 'Reflection' kavramını anlayabilmemiz için aşağıdaki basit örnek uygulama geliştirilmiştir.
Uygulama için 'MyClass' isminde bir Class oluşturuldu ve semboilk fonksiyonlar eklendi.
Örnek:

-MyClass.java:
package com.java.reflection;
public class MyClass {

private String name;
private int age;
private int ID;
public MyClass(){
///..
}

public void setName(String _name){
        name = _name;
}
public String getName(){
return name;
}

public void setAge(int _age){
age = _age;
}
public int getAge(){
return age;
}

public String toString(){
return name +" " + age; 
}
}

-Main.java:
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) {
/*
* MyClass.java Classı içersinde bulunan fonksiyonları-methodları listeleyeceğiz.
* Fonksiyonları elde edebilmek için 'reflect' paketi altında bulunan 'Method' Class'ı kullanılıyor.
*/
Method[] methods = MyClass.class.getMethods();//fonksiyon dizisi.
for(Method method: methods){//fonksiyon elde etme.
String name = method.getName();//fonksiyon ismine erişim.
System.out.println(name);
}

}
}
Çıktı:
toString
getName
setName
setAge
getAge
wait
wait
wait
equals
hashCode
getClass
notify
notifyAll

NOT: Java'da her Class aslında 'Object' class'ı taban alır. Yani gizli bir 'extends' işlemi uygulanır.
Bu durumda oluşturmuş olduğumuz 'MyClass' aslında 'Myclass extends Object' şeklinde konum alır.
Dolayısıyla yukarıdaki çıktıda Object class içeriğine ait fonksiyonlar da listelenmiştir.
Ancak aşağıda verilen örnekte sadece 'MyClass' içeriğine ait fonksiyonlar listelenecektir(kullanım farkını inceleyiniz).

Reflection işleminde belirtilen Class içeriğine ait fonksiyonları aşağıdaki gibi de elde edebiliriz.
Örnek:
public class Main {
public static void main(String[] args) {
try {
//erişilecek Class ismi paket ismi dahil açık şekilde belirtiliyor.
Class cls = Class.forName("com.java.reflection.MyClass");
//getDeclaredMethod fonksiyonu ile tüm fonksiyonlar Method[] dizi türünden döndürülüyor.
Method[] methods = cls.getDeclaredMethods();
for(Method method:methods){
System.out.println(method.getName());
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
Çıktı:
toString
getName
setName
setAge
getAge


Reflection kavramını biraz daha ileri götürelim ve MyClass içersinde bulunan fonksiyonlara parametre gönderip işletelim.
Aşağıda verilen örneği ve çıktıyı inceleyiniz.
Main.java:
public class Main {
public static void main(String[] args) {
try {
//erişilecek Class ismi paket ismi dahil açık şekilde belirtiliyor.
Class cls = Class.forName("com.java.reflection.MyClass");
//MyClass için instance oluştur.
Object obj =cls.newInstance();
/*setName fonksiyonu elde etmek için getMethod 1.parametre fonksiyon ismi,
* 2.parametre ise setName fonksiyonuna ait parametre türü belirleniyor.
* setName fonksiyonumuz 'String' türünde bir parametre aldığı için 'String.class'
* referansı belirleniyor.
* Bu durumda int parametre alan setAge fonkisyonunu için 'Integer.TYPE' belirlenmelidir.

*/
Method method1 = cls.getMethod("setName", String.class);
//fonksiyonumuzun ismi:
       System.out.println(method1.getName());
       //fonksiyonumuzun geri döndürdüğü değer tipi:
       System.out.println( method1.getReturnType());
       //invoke ile setName fonkisyonuna parametre gönderiyoruz:
       method1.invoke(obj, "KERİM FIRAT");
       
       /*setName fonksiyonunu çağırmak için nesneler oluşturuluyor.
        * cls.getMethod 2. parametrenin 'null' olduğuna dikkat edin.
        * Şayet bir fonksiyon parametre almıyorsa buraya null değer geçilir.
        * Aynı durum invoke çağrıldığında da uygulanmalıdır.
        */
       Method method2 = cls.getMethod("getName", null);
       //fonskiyon değeri elde etmek için invoke çağrılıyor:
       Object return_value1 = method2.invoke(obj, null);
       System.out.println("Adı-Soyadı:"+return_value1.toString());
       
       Method method3 = cls.getMethod("setAge", Integer.TYPE);
       method3.invoke(obj, 34);
       Method method4 = cls.getMethod("getAge", null);
       Object return_value2 = method4.invoke(obj, null);
       System.out.println("Yaş:"+return_value2);
           
}catch (Exception e) {
e.printStackTrace();
}
}
}
Çıktı:
setName
void
Adı-Soyadı:KERİM FIRAT
Yaş:34

Not:
Reflect paketi inceleme:https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/package-summary.html
Method Class inceleme: https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html
İyi çalışmalar.

1 Mayıs 2016 Pazar

-Android Custom Component 1-

Merhabalar,
Android uygulama geliştirirken genellikle standart componentler(bileşenler) kullanıyoruz. 
Ancak sözkonusu görsel tasarım ve/veya daha kapsamlı işlevlere sahip bileşenlere ihtiyaç duyulduğunda,ücretli veya kendi ihtiyacımıza yönelik component geliştirme seçeneklerini ele alıyoruz.
Bu makalede çeşitli özellikler kazandırılmış bir TextView bileşeni geliştirilmiştir.
Proje ile ilgili kaynak dosyaların içerikleri aşağıda yer almaktadır. Gerekli açıklamalar yapılmıştır.

1. Adım: "res/values/attrs.xml" dosyası oluşturunuz ve aşağıdaki içeriği uygulayınız.
-attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name ="MyTextView">
        <!-- gölgeleme: -->
        <attr name="fancyText" format="boolean"/>
        <!-- arka plan renk: -->
        <attr name="textBackColor" format="string" />
        <!-- metin rengi: -->
        <attr name="textColor" format="string"/>
        <!-- boyutu: -->
        <attr name="fontSize" format="float"/>
        <!-- ayırıcı(tarih,telefon no vb gibi kullanımlar için: -->
        <attr name="delimiter" format="string"/>
        <!-- tarih: -->
        <attr name="dateMod" format="boolean" />
         <!-- telefon no: -->
   <attr name="phoneNumberMod" format="boolean" />
    </declare-styleable>
</resources>


2.Adım: TextView bileşeni kullanılacak arayüz(layout) içeriği:
-activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res/com.example.androidtest1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidtest1.MainActivity" >

    <!--  
    //özel nitelik kapsamında geliştirdiğimiz bileşenleri kullanabilmemiz-erişebilmemiz 
    için bu satırı(xmlns:custom)  satırı ilgili layout'da kullanmalıyız.
    Aksi taktirde "com.paketadi.KontrolIsmi" şeklinde kullanımı mümkün olmaz.
    xmlns:custom="http://schemas.android.com/apk/res/com.example.androidtest1"
    -->
    <!-- TextView'dan extends edilen MyTextView nesnesi(paket yoluna dikkat!): -->
    <com.example.androidtest1.MyTextView
        android:id="@+id/myTextView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        custom:dateMod="true"
        custom:delimiter="/"
        custom:fancyText="true"
        custom:textBackColor="red" />
</RelativeLayout>


3.Adım: Nitelik(attribute) kazandırılacak bileşene(TextView) ait içerik.
-MyTextView.java:


package com.example.androidtest1;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.widget.TextView;
import android.widget.Toast;

public class MyTextView extends TextView{
 public String delimiter;
 public boolean fancy_text;
 public String text_back_color;
 public String text_color;
 public boolean text_bold;
 public float text_size;
 public int font_size;
 public boolean date_mod;
 public boolean phone_mod;
 
public MyTextView(Context context) {
super(context);
}

public MyTextView(Context context ,AttributeSet attrs){
super(context,attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView );
     int index_c = typedArray.getIndexCount();
     for (int i = 0; i < index_c; ++i) 
     {
        int attr = typedArray.getIndex(i);
        switch (attr)
        {
        
          //tarih ayıraç için mod:
           case R.styleable.MyTextView_dateMod:
            date_mod = typedArray.getBoolean(attr, false);
            break;
           
           //telefon numarası içeriği için ayırac modu:
           case R.styleable.MyTextView_phoneNumberMod:
            phone_mod = typedArray.getBoolean(attr, false);
            break;
           
          //tarih,telefon no vb. gibi işlemlerde ayırıcı(sperate) olarak kullanmak istenirse:
           case R.styleable.MyTextView_delimiter:
           delimiter = typedArray.getString(attr);
           Toast.makeText(getContext(), "delimiter", 1000).show();
           break;

           //içerik gölgeleme:
           case R.styleable.MyTextView_fancyText:
           fancy_text = typedArray.getBoolean(attr, false);
           fancyText();
           break;
           
           case R.styleable.MyTextView_textBackColor:
            text_back_color = typedArray.getString(attr);
            customBackColor();
            break;
           case R.styleable.MyTextView_textColor:
            text_color = typedArray.getString(attr);
            customTextColor();
            break;
          
        }
     }
     dateNow();
              phoneNumber();
     typedArray.recycle();
}//Constructur

private void dateNow() {
if(date_mod){
     SimpleDateFormat dateFormat = 
     new SimpleDateFormat("dd" + delimiter + "MM" + delimiter + "yyyy");
     String today = dateFormat.format(Calendar.getInstance().getTime());
     this.setText(today);  
}
  }
private void phoneNumber(){
//..
//string formatında delimiter kullan..
if(phone_mod){
//formatlama..
}
}

  private void fancyText() {
     if(fancy_text){
        this.setShadowLayer(12, 5, 5, Color.rgb(44, 125, 12));
     }
  }
  private void customBackColor(){
  Color c = new Color();
  int color = c.parseColor(text_back_color);
 this.setBackgroundColor(color);
  }
  private void customTextColor(){
  Color c = new Color();
  int color = c.parseColor(text_color);
  this.setTextColor(color);
  }
}


MyTextView bileşenine erişmek ve kullanmak standart şekilde olduğu için tekrardan yazmaya ihtiyaç duyulmamıştır.
İyi çalışmalar.