顯示具有 <心得> 標籤的文章。 顯示所有文章
顯示具有 <心得> 標籤的文章。 顯示所有文章

2013年3月31日 星期日

<心得> Introduce class interface in Grasshopper C#

目標 : 介紹基本介面關係概念以及簡單介面範例。

參考文獻 :

http://www.cnblogs.com/oomusou/archive/2007/05/07/738311.html


////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//此處描述 :

interface用在當一個物件須和其他物件共同合作時,為了確保其他物件有使者想要的method,所以定下interface,interface就是多個class中裡面有許多相同的method,所以抽取出來作為介面讓大家共同使用,可以在各自的介面中使用相同method名子卻可以有不同的功能。

而abstract class是用在整個繼承體系的最上層,用來定義出整個繼承體系該有哪些method,子類別可以對這些method加以override或維持和abstract class相同的功能,使用繼承技術時,我們會將所有method由abstract class去宣告,然後由各子類別去override,若不得已某些class有自己的特殊method,則由該class自行宣告。關於inheritance請參考Introduce class inheritance in Grasshopper C#

在OO主要有兩種技術:繼承(Inheritance)和組合(Composition),而abstract class就是用在使用繼承技術時,而interface則是用在使用組合技術時。

一旦使用組合時時,就牽涉到一個問題,你如何確保被你組合的物件有某個method當你使用繼承時,因為所有的method都會被繼承,這不是問題,但組合就不一樣了,所以你必須建立一個interface,強迫要被你組合的物件,需實做這個interface,這樣當你要使用該物件時,才能確保有某個method可以呼叫。

由Fig01 我們可以看出有兩個基本的父層(Base),然後子層Parent(Parent繼承Base)和子層child(child繼承Parent)分別繼承上層的關係,只有在Parent中創建method 的方法叫做ApplyEdiable然後子層Child 繼承ApplyEdiable的method

由Fig02 因為ParentA 和 ParentB 有共同的method 叫做ApplyEdiable,所以我們創建BaseC讓裡面擁有名為ApplyEdiable的method,再創建一個interface名為IBaseCAction來真正實踐ApplyEdiable的內部功能,這樣在ChildA、ChildB就可以共同使用ApplyEdiable的method


Fig 01. inheritance 繼承關係圖


Fig 02.interface 介面關係圖


////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//此處示範基本interface創建方式

//使用關鍵字interface
//介面名為
IcircleA
//在介面中只能宣告方法名子與參數,真正實作部分必須在各類別使用中實現
  public interface IcircleA{
    Circle createCircle(Point3d center, double rad);
  }

//類型shapeA  使用介面 IcircleA
  public class shapeA : IcircleA{

    public Circle createCircle(Point3d center, double rad){
      Circle mycircle = new Circle(center, rad);
      return mycircle;
    }

  }

//創建類型shapeA  
//並呼叫介面方法且指定參數

  shapeA mytest = new shapeA();
    A = mytest.createCircle(new Point3d(0, 0, 0), 10.0);

輸出圖像:
使用interface所創建的圓

//如果遇上多個interface 中有著相同的名稱method,必須創建原始介面,才能呼叫方法
//參考文章 : http://msdn.microsoft.com/zh-tw/library/ms173157(v=vs.80).aspx

//請注意interface IcircleA and IcircleB擁有相同的mehod 名稱為 createCircle


  public interface IcircleA{
    Circle createCircle(Point3d center, double rad);
  }

  public interface IcircleB{
    Circle createCircle(Point3d center, double rad);
  }


//class shapeA實行介面 IcircleA,IcircleB兩個介面
//注意 Circle IcircleA.createCircle 的Circle 之前不能加上public

 public class shapeA : IcircleA,IcircleB{

    Circle IcircleA.createCircle(Point3d center, double rad){
      Circle mycircle = new Circle(center, rad);
      return mycircle;
    }

    Circle IcircleB.createCircle(Point3d center, double rad){
      Circle mycircle = new Circle(center, rad / 2);
      return mycircle;
    }

  }


//instance shapeA 

    shapeA mytest = new shapeA();

//呼叫createCircle 藉由已經存在的mytest物件中執行名為IcircleA的介面
//因為使用者有兩個相同的method 所以必須明確的告知compiler 哪個才是你想執行的介面方法
//所以呼叫到介面的那層 

    shapeA mytest = new shapeA();

    IcircleA circleA = (IcircleA) mytest;
    A = circleA.createCircle(new Point3d(0, 0, 0), 10.0);

    IcircleB circleB = (IcircleB) mytest;
    B = circleB.createCircle(new Point3d(0, 0, 0), 10.0);



輸出圖像:



使用相同名稱的method所創建的圓



////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//使用時機 


>>何時使用main function
若公司不到5個人,老闆只要將要做的事情規定好(function),然後指定某個人去做某件事情即可(main function),這種『中央集權』的方式就是『程序導向』,在小公司是很有效率的。

>>何時使用OOP
若是上千人的公司,老闆不可能同時指揮所有人,所以有經理,科長等管理階層出現,老闆只要管好經理,經理只要盯住科長,科長再分配事情給小職員做,這種『分層負責』,每個人將自己分內做好的方式,就是『物件導向』,大公司一定得用這種方式才能管理。
軟體開發也是一樣,小程式用『程序導向』方式寫就很方便,但大程式則必須用『物件導向』方式才好管理,軟體開發和企業管理是相通的。
>>何時要用 interface 而不要使用父類別
盡量用 interface, 盡量不要用父類別, 如果例子簡化成 '動物一定有眼睛, 需要由各子類別去實作', 而 '動物' class 裡也沒別的定義, 那麼就是使用 interface 的標準狀況, 完全不必考慮是否要使用 abstract class

>>何時要用父類別而不要使用 interface
如果父類別有寫一些 method, property ,你想讓子類別能繼承後就順便有它們,就用父類別, 至於父類別要宣告成 class or abstract class, 看父類別想不想被 new

在 C#, VB.NET 語言裡, 一個類別只能繼承一個 class, 可以實作多個 interface, 所以換個角度來看, 寫程式時不要這麼 '敗家' , 隨便地就將維一一個繼承的機會就用掉了  


////////////////////////////////////////////////////////////////////////////////////////////////////////////////

2013年3月29日 星期五

<心得> Introduce class inheritance in Grasshopper C#

目標 : 介紹基本繼承關係概念以及簡單繼承範例。


參考文獻 :

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//此處描述 :

在介紹繼承之前先簡單介紹一下類型(class)

class 中包含三個部分
1.//properties
2.//constructor
3.//methods

在OO(object-oriented )語言中就像C# /C /C++/JAVA所有概念都是由物件所組成,而class就像是藍圖一樣,像室內設計師在設計圖面時,可能會有水電圖、天花圖、平面設計圖、迴路圖等圖面,而藍圖就是管理這些所有圖面的資料夾。

依照設計師的使用需求不同,設計師可以套繪不同的平面在同一個底圖上。我們可以把所有的圖面(水電圖、天花圖)想像成class中的methods,當設計師今天只需要平面設計圖與天花圖的時候,只要從藍圖中抽取出需要的圖面即可,這樣的藍圖(class)也間接的幫設計師做好管理打包(encapsulation)的工作。

單然很多資料夾之間也可能存在著檔案共享或是繼承的關係,所以往後再繼續介紹類型的其他好用之處。

msda介紹class
class is a construct that enables you to create your own custom types by grouping together variables of other types, methods and events. A class is like a blueprint. It defines the data and behavior of a type. 


////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//此處示範基本class 創建方式

//創建圓法一:

  public class WeiA{

//properties
//型態內建的變數我們就稱之為properties

    Point3d point;
    double rad;

//constructor
//你可以有多個constructor在這裏我們有兩個,如果有多個以上constructor我們稱之為overload
//要注意的是constructor 的名稱必須與類型名稱一致,而且當類型一旦被創建的//同時,即是
//呼叫constructor,constructor並不會回傳任何型態。
//此處this 關鍵字是把constructor 中的parameter 當成類型中的argument來使用的意思

    public WeiA(){
    }

    public WeiA(Point3d point, double rad){
      this.point = point;
      this.rad = rad;
    }

//methods
//即是類型中你要使用的方法

    public Circle drawWeiA(){
      Circle circleA = new Circle(point, rad);
      return circleA;
    }

  }


//以此為例 double mynumber
//就像我們常用的double 雙浮點小數
//我們創建名為mynumber的物件,型態為double 
//在此我們創建名為myA 的物件,型態為WeiA 
//而這部分new WeiA();即是呼叫class 中的constructor

 WeiA myA = new WeiA(new Point3d(0, 0, 0), 10.0);


    A = myA.drawWeiA();
當我們創建好myA 的物件時可以看到使用者自訂的類型出現在選單中。而這個選單就是使用者所創建的method

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

輸出圖像:
你已經簡單的使用類型創建出一個圓
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//創建圓法二:


當然你也可以用rhinocommond SDK的方法來直接創建一個圓(因為C#本身就是OO概念,我在這邊只是在示範
如何創建自己的類型,使用畫圓的方式而已)

程式碼:
Circle mycircle = new Circle(new Point3d(0, 0, 0), 10.0);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//此處補充修飾詞

類別或成員可以使用下面幾個修飾詞來定義存取方式:
public:存取沒有限制。
private:只有類別本身能存取。
protected:只有類別本身和其衍伸類別本身能存取。
internal:只有同一個 Namespace 的地方能看到。

當不希望類別再被繼承下去,可以使用 selected 修飾詞,類別將不可再被繼承,否則會發生錯誤訊息。
EX:public sealed class A{}

相對,如果希望類別一定要被繼承後才可以使用,本身無法直接使用時,可以使用 abstract 修飾詞。
EX:public abstract class B{}



範例:

  private class WeiA{

WeiA(){
}

  }

or 


  protected class WeiA{

WeiA(){
}

  }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//此處示範基本inheritance 創建方式

//WeiA 是superclass也是父層


public class WeiA{


    Point3d point;
    double rad;

    public WeiA(){
    }

    public WeiA(Point3d point, double rad){
      this.point = point;
      this.rad = rad;
    }

    public  Circle drawWeiA(Point3d point, double rad){
      Circle circleA = new Circle(point, rad);
      return circleA;
    }

  }

//WeiB繼承WeiA的類型內部資料
//WeiB稱之為subclass也是子層

  public class WeiB : WeiA{

    public WeiB(){
    }

  }




    //create object myA//
    WeiA myA = new WeiA();

    //create object myB//
    WeiB myB = new WeiB();


    A = myA.drawWeiA(new Point3d(0, 0, 0), 10.0);
    B = myB.drawWeiA(new Point3d(0, 0, 0), 5.0);

//在此我們要注意的是在myB的物件中並沒有創建drawWeiA的method,使用者卻在創建myB的物件後可以調動
//drawWeiA的方法,原因是 WeiB : WeiA(WeiB類型繼承了WeiA的內部資料)




WeiB類型繼承了WeiA的內部資料
使用inheritance 創建出基本圖形
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//此處示範基本virtual and override創建方式

//當我們從父層繼承而來的方法時卻發現內部資料需要被改變"但method名子"卻又相同時,那該如何解決?
//答案就是使用關鍵字virtual and override
//在父層相同名子的method 中前面加入關鍵字virtual 當作抽象的方法
//在子層相同名子的method 中前面加入關鍵override 當作覆寫的方法


  public class WeiA{

    Point3d point;
    double rad;

    public WeiA(){
    }

    public WeiA(Point3d point, double rad){
      this.point = point;
      this.rad = rad;
    }

    public  virtual Circle drawWei(Point3d point, double rad){
      Circle circleA = new Circle(point, rad);
      return circleA;
    }

  }

  public class WeiB : WeiA{

    public WeiB(){
    }

    public  override Circle drawWei(Point3d point, double rad){
      Circle circleA = new Circle(point, rad / 2);
      return circleA;
    }

  }





    //create object myA//
    WeiA myA = new WeiA();

    //create object myB//
    WeiB myB = new WeiB();


    A = myA.drawWei(new Point3d(0, 0, 0), 10.0);
    B = myB.drawWei(new Point3d(0, 0, 0), 10.0);

//我們可以在此發現都是調用一樣的方法drawWei 輸入一樣的參數 new Point3d(0, 0, 0), 10.0
//那為什麼出來的圖形卻是不一樣,答案就是使用覆寫method內部資料的關鍵字。
// A = myA.drawWei(new Point3d(0, 0, 0), 10.0);
// B = myB.drawWei(new Point3d(0, 0, 0), 10.0);





使用一樣的method 與參數,卻產生出不一樣的半徑圓



////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//此處延續virtual and override補充 new
//資料再補充 override and new 的差別
























2013年3月10日 星期日

<心得> Grasshopper /doc. and rhutil./ 差別

原文出處 :
http://www.grasshopper3d.com/forum/topics/doc-and-rhutil

心得: 比較 doc 與 rhuil 的差別

doc -> 
doc is short for "document". It is a class that offers access to a specific 3dm file. It allows you to add and retrieve objects from that file, access the layers, the linetypes, the materials etc. etc.

doc是一個class 提供給使用者直接取出rhino 3dm文件黨中的資訊,如圖層、模型材料、任何模型中的資訊。

rhutil ->
rhutil is a class that provides a wide array of static (Shared in VB) functions. These functions can be called anytime, anywhere as they are not tied to a specific instance of an object (that's what "shared" means).

rhutil 是一個class 提供使用者一個工具模組(當然是使用static class的方式建成)分享於GH VB /C# component (legacy)。

重點->
In the new SDK (RhinoCommon), RhUtil no longer exists. Neither does OnUtil. We've put the shared functions on the types that seem to make the most sense, instead of lumping everything into a single bucket.


在新版的SDK 使用者參照表中,rhutil 和OnUtil此工具模組不再存在給使用者使用,David Rutten 將會把rhutil 和OnUtil 相對應的功能放置在相對應的類別當中。

像是使用者要創建一個封閉平面,再legacy component 可以調用RhUtil.RhinoCreateEdgeSrf();的方法,但再新版的component中使用者必須使用使用brep class 類別中的 Brep.CreatePlanarBreps();此種方法。

但在往後的GH版本,David Rutten還是會保留legacy vb/c#的版本,所以使用這還是可以使用傳統版本,使用傳統版本就可以繼續使用rhutil 和OnUtil的方法。

rhino common sdk 線上版->
http://4.rhino3d.com/5/rhinocommon/




圖片說明 :
grasshopper VB legacy component -> 邊線創建平面的呼叫方法
此本PDF下載地址http://www.grasshopper3d.com/page/scripting-and-code-tutorials




圖片說明 :

rhino common sdk
grasshopper c# component ->  邊線創建平面的呼叫方法