组合和继承
组合:只需要在新的类中产生现有类的对象,新的类是由现有类的对象组成的,这种方法称为组合
继承:按照现有类的类型来创建新类,不需要改变现有类的形式,采用现有类的形式并且在其中添加新的代码。
组合
只需要将对象引用置于新类中即可
class WaterSource{
private String s;
WaterSource(){
System.out.println("WaterSource() -----");
s = "Constructed -----";
}
@Override
public String toString() {
return s;
}
}
public class SprinklerSystem {
private WaterSource source = new WaterSource();//对象引用在新类当中
@Override
public String toString() {
return "SprinklerSystem{
"source=" + source +
}';
}
public static void main(String[] args) {
SprinklerSystem sp = new SprinklerSystem();
System.out.println(sp);
}
}
toString
上方代码,由于编译器需要一个String但只有一个对象的时候,此方法就会被调用,可以将两个String连接在一起,并且将结果返回在sout中
初始化
编译器不会为每一个引用都创建一个默认的对象,初始化引用在以下位置
1.在定义对象的地方。意味着会在构造器被调用之前被初始化
2.在类的构造器中
3.惰性初始化:在正要使用对象之前,在生成对象不值得或者没有必要每次都生成对象的情况下
4.实例初始化
class Soap{
private String s;
Soap(){
System.out.println("soap()");
s = "Constructed";
}
}
public class Bath {
String
s1 = "Happy",
s2 = "Happy",//在定义对象的地方
s3,s4;
private Soap castille;
private int i ;
private float toy;
Bath(){
System.out.println("Inside Bath()");
s3 = "Joy";
toy = 3.14f;//在类的构造器中
castille = new Soap();
{
i = 2;//实例初始化
}
}
@Override
public String toString() {
if (s4 == null){
s4 = "joy";//惰性初始化:在正要使用对象之前,在生成对象不值得或者没有必要每次都生成对象的情况下
}
return "Bath{" +
"s1='" + s1 + '\'' +
", s2='" + s2 + '\'' +
", s3='" + s3 + '\'' +
", s4='" + s4 + '\'' +
", castille=" + castille +
", i=" + i +
", toy=" + toy +
'}';
}
public static void main(String[] args) {
Bath bath = new Bath();
System.out.println(bath);
}
}
继承
继承用extends关键字实现,声明“新类与旧类相似”
当创建一个类的时候如果没有明确从哪个类中继承,否则就是从Object中进行继承的
class Cleanser{
private String s = "Cleanser";
int i = 0;
float f = 3.14f;
public void append(String a){
s +=a;
}
public void dilute(){
append(" dilute() ");
}
public void apply(){
append(" apply() ");
}
public void scrub(){
append(" scrub() ");
}
@Override
public String toString() {
return s;
}
public static void main(String[] args) {
Cleanser cl = new Cleanser();
cl.dilute();
cl.apply();
cl.scrub();
System.out.println(cl);
}
}
public class Detergent extends Cleanser {
int i1 = 0;
public void scrub(){
append(" [Detergent scrub()] ");
}
public static void main(String[] args) {
Cleanser cleanser = new Detergent();
System.out.println(cleanser.i);
System.out.println(cleanser.f);
cleanser.apply();
System.out.println(cleanser);
}
}
初始化基类
当创建了一个导出类的对象的时候,这个对象还包含了一个基类的子对象,这个子对象和直接用基类创建对象是一样的,但是这样是来自于外部,而前者基类的子对象是包装在导出类对象的内部的
JAVA会自动在导出类的构造器中插入对基类构造器的调用
但是如果基类的构造器只有一个带参数的构造器的话,必须用super显示的调用构造器
如果不写的话,基类必须有一个默认构造器
class Art{
Art(){
System.out.println("Art Constructed ------");
}
}
class Drawing extends Art{
Drawing(){
System.out.println("Drawing Constructed");
}
}
public class Cartoon extends Drawing {
public static void main(String[] args) {
new Cartoon();
}
}
class Game{
Game(int i){
System.out.println("Game constructed ---");
}
}
class BoardGame extends Game{
BoardGame(int i){
super(i);//用super
System.out.println("Board Constructed ---");
}
}
public class Chess extends BoardGame {
Chess(int i){
super(i);
System.out.println("Chess Constructed ---");
}
public static void main(String[] args) {
new Chess(20);
}
}
代理
将一个成员对象置于所构造的类的(就像组合一样),但是要在新的类中暴露出来这个成员对象当中的所有方法
class SpaceShipControls{
void up(int velocity){}
void down(int velocity){}
void left(int velocity){}
void right(int velocity){}
void forward(int velocity){}
void back(int velocity){}
void turboBoost(int velocity){}
}
public class SpaceShipDelegation {
private String name;
private SpaceShipControls controls = new SpaceShipControls();
public SpaceShipDelegation(String name){
this.name = name;
}
public void up(int velocity){
controls.up(velocity);
}
public void down(int velocity){
controls.down(velocity);
System.out.println("下降了一百米");
}
public void left(int velocity){
controls.left(velocity);
}
public void right(int velocity){
controls.right(velocity);
}
public void forward(int velocity){
controls.forward(velocity);
}
public void back(int velocity){
controls.back(velocity);
}
public void turboBoost(int velocity){
controls.turboBoost(velocity);
}
public static void main(String[] args) {
SpaceShipDelegation sp = new SpaceShipDelegation("Nasa Ship");
sp.down(100);
}
}
结合使用组合和继承
class Plate{
Plate(int i){
System.out.println("plate constructed ---");
}
}
class DinnerPlate extends Plate{
DinnerPlate(int i){
super(i);
System.out.println("DinnerPlate constructed ---");
}
}
class Utensil{
Utensil(int i){
System.out.println("Utensil constructed ---");
}
}
class Spoon extends Utensil{
Spoon(int i){
super(i);
System.out.println("Spoon Constructed ---");
}
}
class Fork extends Utensil{
Fork(int i){
super(i);
System.out.println("Fork constructed ---");
}
}
class Knife extends Utensil{
Knife(int i){
super(i);
System.out.println("Knife constructed ---");
}
}
class Custom{
Custom(int i){
System.out.println("Custom constructed ---");
}
}
public class PlaceSetting extends Custom{
private Spoon sp;
private Knife kn;
private Fork fo;
private DinnerPlate dp;
public PlaceSetting(int i){
super(i + 1);
sp = new Spoon(i + 2);
fo = new Fork(i + 3);
kn = new Knife(i + 4);
dp = new DinnerPlate(i + 5);
System.out.println("PlateSetting constructed ---");
}
public static void main(String[] args) {
PlaceSetting placeSetting = new PlaceSetting(9);
}
}
清理
名称屏蔽
如果基类中有某个多次被重载的方法名称,如果再导出类中重新定义该方法名称并不会屏蔽在基类中的任何版本
class Homer{
char doSth(char c){
System.out.println("doSth (char)");
return c;
}
float doSth(float f){
System.out.println("doSth (float)");
return f;
}
}
class MilHouse{}
class Bart extends Homer{
void doSth(MilHouse m){
System.out.println("doSth (MilHouse)");
}
}
public class Hide{
public static void main(String[] args) {
Bart bart = new Bart();
bart.doSth('x');
bart.doSth(1.0f);
bart.doSth(1);
bart.doSth(new MilHouse());
}
}
在组合和继承之间左选择
组合技术通常在新类中使用现有类的功能而非它的接口这种情形
class Engine{
public void start(){}
public void rev(){}
public void stop(){}
}
class Wheel{
public void inflate(int psi){
System.out.println("哈哈哈");
}
}
class Window{
public void rollUp(){
System.out.println("窗户摇上来了");
}
public void rollDown(){}
}
class Door{
Window window = new Window();
public void open(){}
public void close(){}
}
public class Car {
public Engine engine = new Engine();
public Wheel[] wheels = new Wheel[4];
public Door left = new Door(),
right = new Door();
public Car(){
for (int i = 0 ; i < 4 ; i++){
wheels[i] = new Wheel();
}
}
public static void main(String[] args) {
Car car = new Car();
car.left.window.rollUp();
car.wheels[0].inflate(2);
}
}
protect关键字
对于类用户而言使私有的,对于它的子类来说是可以访问的
class Villain{
private String name;
protected void set(String nm){
this.name = nm;
}
public Villain(String name){
this.name = name;
}
@Override
public String toString() {
return "i am a villain and my name is = " + name;
}
}
public class Orc extends Villain {
private int orcNumber;
public Orc(String name , int orcNumber){
super(name);
this.orcNumber = orcNumber;
}
public void change(String name , int orcNumber){
set(name);
this.orcNumber = orcNumber;
}
@Override
public String toString() {
return "Orc " + orcNumber + ": " + super.toString();
}
public static void main(String[] args) {
Orc orc = new Orc("王博涛", 22);
System.out.println(orc);
orc.change("王庚鑫",25);
System.out.println(orc);
Villain villain = new Villain("hahah");
System.out.println(villain);
}
}
如果父类方法为protected访问权限的话,子类可以扩大为public权限
对静态方法来说,子类可以拥有父类的静态方法,子类同样可以定义与基类一样的static方法,但不属于重写.