Ⅰ 談談java中的繼承與組合
繼承和組合的概念
在新類里簡單地創建原有類的對象 我們把這種方法叫作 組合 因為新類由現有類的對象合並而成 我們只是簡單地重復利用代碼的功能 而不是採用它的形式
第二種方法是創建一個新類 將其作為現有類的一個 類型 我們可以原樣採取現有類的形式 並在其中加入新代碼 同時不會對現有的類產生影響 這種魔術般的行為叫作 繼承 (Inheritance) 涉及的大多數工作都是由編譯器完成的 對於面向對象的程序設計 繼承 是最重要的基礎概念之一 對於組合和繼承這兩種方法 大多數語法和行為都是類似的(因為它們都要根據現有的類型生成新類型)
組合也就是一個類的對象是另外一個類的成員 一般的程序都有組合的意味 只不過是基本數據類型是成員變數 下面請看具體的例子
class Head
{
Head(){
System out println( head );
}
}
class Body
{
Body(){
System out println( body );
}
}
class Person()
{
Head h=null;
Body b=null;
Person() //人是由頭和身體組成的 Head和Body的對象是Person的一部分
{
h=new Head();
b =new Body();
}
}
繼承作為面向對象的三個重要特性的一個方面 在面向對象的領域有著及其重要的作用 好像沒聽說哪個面向對象的語言不支持繼承
class Person
核扮桐{
private String name=null;
private int age= ;
public Person(String n int a)
{
name=n;
age=a;
}
int getAge()
{
return age;
}
String getName()
{
return name;
}
void getDescription()
{
System out println( name: +name+ + age: +age);
}
}
class Student extends Person
{
private String studno=null;
public Student(String n String no int a)
{
super(n a);
studno=no;
}
}
說明:Student類中有三個成員變數name age studno和一個方法getDescription();
注意:子類繼承了父類的所有變數和函數 只是缺孫子類不能訪問父類的private類型的變數和函數 其實privae類型的變數還是繼承到子類中的
無論還是繼承 都允許我們將子對象置於自己的新類中 大家或許會奇怪兩者間的差異 以及到底該如何選擇
如果想利用新類內部一個現有類的特性 而不想使用它的介面 通常應選擇組合 也就是說 我們可嵌入一個對象 使自己能用它實現新類的特性 但新類的用戶會看到我們已定義的介面 而不是來自嵌入對象的介面 考慮到這種效果 我們改坦需在新類里嵌入現有類的private對象
有些時候 我們想讓類用戶直接訪問新類的組合 也就是說 需要將成員對象的屬性變為public 成員對象會將自身隱藏起來 所以這是一種安全的做法 而且在用戶知道我們准備合成一系列組件時 介面就更容易理解 car(汽車)對象便是一個很好的例子
class Engine {
public void start() {}
public void rev() {}
public void stop() {}
}
class Wheel {
public void inflate(int psi) {}
}
class Window {
public void rollup() {}
public void rolldown() {}
}
class Door {
public Window window = new Window();
public void open() {}
public void close() {}
}
public class Car {
public Engine engine = new Engine();
public Wheel[] wheel = new Wheel[ ];
public Door left = new Door()
right = new Door(); // door
Car() {
for(int i = ; i < ; i++)
wheel[i] = new Wheel();
}
public static void main(String[] args) {
Car car = new Car();
car left window rollup();
car wheel[ ] inflate( );
}
} ///:~
由於汽車的裝配是故障分析時需要考慮的一項因素(並非只是基礎設計簡單的一部分) 所以有助於客戶程序員理解如何使用類 而且類創建者的編程復雜程度也會大幅度降低
如選擇繼承 就需要取得一個現成的類 並製作它的一個特殊版本 通常 這意味著我們准備使用一個常規用途的類 並根據特定的需求對其進行定製 只需稍加想像 就知道自己不能用一個車輛對象來組合一輛汽車——汽車並不 包含 車輛 相反 它 屬於 車輛的一種類別 屬於 關系是用繼承來表達的 而 包含 關系是用組合來表達的
protected
現在我們已理解了繼承的概念 protected這個關鍵字最後終於有了意義 在理想情況下 private成員隨時都是 私有 的 任何人不得訪問 但在實際應用中 經常想把某些東西深深地藏起來 但同時允許訪問衍生類的成員 protected關鍵字可幫助我們做到這一點 它的意思是 它本身是私有的 但可由從這個類繼承的任何東西或者同一個包內的其他任何東西訪問 也就是說 Java中的protected會成為進入 友好 狀態
我們採取的最好的做法是保持成員的private狀態——無論如何都應保留對基 礎的實施細節進行修改的權利 在這一前提下 可通過protected方法允許類的繼承者進行受到控制的訪問
import java util *;
class Villain {
private int i;
protected int read() { return i; }
protected void set(int ii) { i = ii; }
public Villain(int ii) { i = ii; }
public int value(int m) { return m*i; }
}
public class Orc extends Villain {
private int j;
public Orc(int jj) { super(jj); j = jj; }
public void change(int x) { set(x); }
} ///:~
可以看到 change()擁有對set()的訪問許可權 因為它的屬性是protected(受到保護的)
再論合成與繼承
lishixin/Article/program/Java/hx/201311/26635
Ⅱ Java中,組合和繼承的區別
1.組合(has-a)關系可以顯式地獲得被包含類(繼承中稱為父類)的對象,而繼承(is-a)則是隱式地獲得父類的對象,被包含類和父類對應,而組合外部類和子類對應。
2.組合關系在運行期決定,而繼承關系在編譯期就已經決定了。
3.組合是在組合類和被包含類之間的一種松耦合關系,而繼承則是父類和子類之間的一種緊耦合關系。
4.當選擇使用組合關系時,在組合類中包含了外部類的對象,組合類可以調用外部類必須的方法,而使用繼承關系時,父類的所有方法和變數都被子類無條件繼承,子類不能選擇。
5.最重要的一點,使用繼承關系時,可以實現類型的回溯,即用父類變數引用子類對象,這樣便可以實現多態,而組合沒有這個特性。
6.還有一點需要注意,如果你確定復用另外一個類的方法永遠不需要改變時,應該使用組合,因為組合只是簡單地復用被包含類的介面,而繼承除了復用父類的介面外,它甚至還可以覆蓋這些介面,修改父類介面的默認實現,這個特性是組合所不具有的。
7.從邏輯上看,組合最主要地體現的是一種整體和部分的思想,例如在電腦類是由內存類,CPU類,硬碟類等等組成的,而繼承則體現的是一種可以回溯的父子關系,子類也是父類的一個對象。
8.這兩者的區別主要體現在類的抽象階段,在分析類之間的關系時就應該確定是採用組合還是採用繼承。
9.引用網友的一句很經典的話應該更能讓大家分清繼承和組合的區別:組合可以被說成「我請了個老頭在我家裡幹活」 ,繼承則是「我父親在家裡幫我幹活"。
Ⅲ 關於各種排列組合java演算法實現方法
一 利用二進制狀態法求排列組合 此種方法比較容易懂 但是運行喊隱頌效率不高 小數據排列組合可以使用
復制代碼 代碼如下: import java util Arrays;//利用二進制演算法進行全排列 //count : //count :
public class test { public static void main(String[] args) { long start=System currentTimeMillis(); count (); long end=System currentTimeMillis(); System out println(end start); } private static void count (){ int[] num=new int []{ }; for(int i= ;i<Math pow( );i++){ String str=Integer toString(i ); int sz=str length(); for(int j= ;j< sz;j++){ str=" "+str; } char[] temp=str toCharArray(); Arrays sort(temp); String gl=new String(temp); if(!gl equals(" ")){ continue; } String result=""; for(int m= ;m<str length();m++){ result+=num[Integer parseInt(str charAt(m)+"")]; } System out println(result); } } public static void count (){ int[] num=new int []{ }; int[] ss=new int []{ }; int[] temp=new int[ ]; while(temp[ ]< ){ temp[temp length ]++; for(int i=temp length ;i> ;i ){ if(temp[i]== ){ temp[i]= ; temp[i ]++; } } int []tt=temp clone(); Arrays sort(tt); if(!Arrays equals(tt ss)){ continue; } String result=""; for(int i= ;i<num length;i++){ result+=num[temp[i]]; } System out println(result); } } }
二 用遞歸的思想攜慧來求排列跟組合 代碼量比較大
復制代碼 代碼如下鄭鄭: package practice;import java util ArrayList; import java util List;
public class Test {
/** * @param args */ public static void main(String[] args) { // TODO Auto generated method stub Object[] tmp={ }; // ArrayList<Object[]> rs=RandomC(tmp); ArrayList<Object[]> rs=cmn(tmp ); for(int i= ;i<rs size();i++) { // System out print(i+"="); for(int j= ;j<rs get(i) length;j++) { System out print(rs get(i)[j]+" "); } System out println(); } }
// 求一個數組的任意組合 static ArrayList<Object[]> RandomC(Object[] source) { ArrayList<Object[]> result=new ArrayList<Object[]>(); if(source length== ) { result add(source); } else { Object[] psource=new Object[source length ]; for(int i= ;i<psource length;i++) { psource[i]=source[i]; } result=RandomC(psource); int len=result size();//fn組合的長度 result add((new Object[]{source[source length ]})); for(int i= ;i<len;i++) { Object[] tmp=new Object[result get(i) length+ ]; for(int j= ;j<tmp length ;j++) { tmp[j]=result get(i)[j]; } tmp[tmp length ]=source[source length ]; result add(tmp); } } return result; } static ArrayList<Object[]> cmn(Object[] source int n) { ArrayList<Object[]> result=new ArrayList<Object[]>(); if(n== ) { for(int i= ;i<source length;i++) { result add(new Object[]{source[i]}); } } else if(source length==n) { result add(source); } else { Object[] psource=new Object[source length ]; for(int i= ;i<psource length;i++) { psource[i]=source[i]; } result=cmn(psource n); ArrayList<Object[]> tmp=cmn(psource n ); for(int i= ;i<tmp size();i++) { Object[] rs=new Object[n]; for(int j= ;j<n ;j++) { rs[j]=tmp get(i)[j]; } rs[n ]=source[source length ]; result add(rs); } } return result; }
}
三 利用動態規劃的思想求排列和組合
復制代碼 代碼如下: package Acm; //強大的求組合數 public class MainApp { public static void main(String[] args) { int[] num=new int[]{ }; String str=""; //求 個數的組合個數 // count( str num ); // 求 n個數的組合個數 count ( str num); }private static void count (int i String str int[] num) { if(i==num length){ System out println(str); return; } count (i+ str num); count (i+ str+num[i]+" " num); }
private static void count(int i String str int[] num int n) { if(n== ){ System out println(str); return; } if(i==num length){ return; } count(i+ str+num[i]+" " num n ); count(i+ str num n); } }
下面是求排列
復制代碼 代碼如下: lishixin/Article/program/Java/JSP/201311/20148
Ⅳ Java編程:組合,繼承和代理的區別
組合的話,是在類中new一個對象,然後就只能調用這個對象的方法了,是死的
而你用代理的話,代理不僅要new那個對象,還要把你想調用這個對象的方法也寫出來,方法實現是通過這個new的對象來實現的,當然你也可以在方法中添加你自己想實現的功能,這樣做又有了繼承中重寫的感覺,所以說代理是繼承和組合的中庸之道,lz可以看看thinking in java7.3章 7.4章 還有網頁鏈接這篇博客,寫的很詳細
Ⅳ java中什麼叫組合
組合就是 A類的對象是B類的成員變數。相當於 A類是B類對象的一個屬性!
組合和繼承都很常見的!