组合
```java
package thinginginJ;
class WaterSource {
private String s;
WaterSource() {
System.out.println("WaterSource()");
s = new String("Constructed");
}
// public String toString() {/// 不用写也可以,因为会从Object 默认集成toString 方法。
// return s;
// }
}
public class SprinklerSystem {
//第一个最简单:在新类里简单地创建原有类的对象。我们把这种方法叫
//作“组合”,因为新类由现有类的对象合并而成。我们只是简单地重复利用代码的
//功能,而不是采用它的形式。
private String valve1, valve2, valve3, valve4;
WaterSource source;
int i;
float f;
void print() {
System.out.println("valve1 = " + valve1);
System.out.println("valve2 = " + valve2);
System.out.println("valve3 = " + valve3);
System.out.println("valve4 = " + valve4);
System.out.println("i = " + i);
System.out.println("f = " + f);
System.out.println("source = " + source);
}
public static void main(String[] args) {
SprinklerSystem x = new SprinklerSystem();
x.print();
}
} /// :~
运行结果:
编译器并不只是为每个引用创建一个默认对象,因为那样会在许多情况下招致不必
要的开销。如希望引用得到初始化,可在下面这些地方进行:
(1) 在对象定义的时候。这意味着它们在构造器调用之前肯定能得到初始化。
(2) 在那个类的构造器中。
(3) 紧靠在要求实际使用那个对象之前。这样做可减少不必要的开销——假如对象
并不需要创建的话。
下面向大家展示了所有这三种方法:
package thinginginJ;
class Soap {
private String s;
Soap() {
System.out.println("Soap()");
s = new String("Constructed");
}
public String toString() {
return s;
}
}
class Bath {
private String
// Initializing at point of definition:
s1 = new String("Happy"), //(1) 在对象定义的时候。这意味着它们在构造器调用之前肯定能得到初始化。
s2 = "Happy",
s3, s4;
Soap castille;
int i;
float toy;
Bath() {
System.out.println("Inside Bath()");
s3 = new String("Joy");//(2) 在构造器中初始化
i = 47; //在构造器中初始化
toy = 3.14f; //在构造器中初始化
castille = new Soap(); //在构造器中初始化
}
void print() {
// Delayed initialization:
if (s4 == null)
s4 = new String("Joy");//(3) 紧靠在要求实际使用那个对象之前。这样做可减少不必要的开销——假如对象
// 并不需要创建的话。
System.out.println("s1 = " + s1);
System.out.println("s2 = " + s2);
System.out.println("s3 = " + s3);
System.out.println("s4 = " + s4);
System.out.println("i = " + i);
System.out.println("toy = " + toy);
System.out.println("castille = " + castille);
}
public static void main(String[] args) {
Bath b = new Bath();
b.print();
}
} /// :~
继承:
通过父类的public方法,照样是可以用私有字段,如下:
package thinginginJ;
//: Detergent.java
//Inheritance syntax & properties
class Cleanser {
private String s = new String("Cleanser fucking");
public void append(String a) {
s += a;
}
public void dilute() {
append(" dilute()");
}
public void apply() {
append(" apply()");
}
public void scrub() {
append(" scrub()");
}
public void print() {
System.out.println(s);
}
public static void main(String[] args) {
Cleanser x = new Cleanser();
x.dilute();
x.apply();
x.scrub();
x.print();
}
}
public class Detergent extends Cleanser {
// Change a method:
public void scrub() {
append(" Detergent.scrub()");
super.scrub(); // Call base-class version super.scrub() 调用的是方法 scrub() //的基类版本。
}
// Add methods to the interface:
public void foam() {
append(" foam()");
}
// Test the new class:
public static void main(String[] args) {
Detergent x = new Detergent();
x.dilute();//明明Cleanser.s 是父类私有的,为何子类Detergent可以用呢.那是因为父类的私有字段虽然子类没有继承,但是不代表不能用呀,
//通过父类的public方法,照样是可以用私有字段滴,当然,如果父类没有public 方法,那也就不能用了.
x.apply();
x.scrub();
x.foam();
x.print();
System.out.println("Testing base class:");
Cleanser.main(args);
}
} /// :~
无论 Cleanser 还是 Detergent 都包含了一个 main() 方法。我们可为
自己的每个类都创建一个 main()
需要着重强调的是 Cleanser 中的所有类都是 public 属性。请记住,倘若省略
所有访问指示符,则成员默认为“友好的”。这样一来,就只允许对包成员进行访
问。在这个包内,任何人都可使用那些没有访问指示符的方法。例
如, Detergent 将不会遇到任何麻烦。然而,假设来自另外某个包的类准备继
承 Cleanser ,它就只能访问那些 public 成员。所以在计划继承的时候,一个
比较好的规则是将所有字段都设为 private ,并将所有方法都设
为 public ( protected 成员也允许派生出来的类访问它;)
注意 Cleanser 在它的接口中含有一系列方
法: append() , dilute() , apply() , scrub() 以及 print() 。由
于 Detergent 是从 Cleanser 派生出来的(通过 extends 关键字),所以它会
自动获得接口内的所有这些方法——即使我们在 Detergent 里并未看到对它们的
明确定义。
如果也给子类定义一个与父类同名的字段的?比如:
private String s ;