Chapter 6 Reusing Classes

This post was republished to 黄立 at 15:00:57 2010-5-18

Chapter 6 Reusing Classes

 

 

Category    Thinking in java note

 

  1. Inheritance syntax

  • Syntax

    使用extend即可。

  • Initializing the base class

    Testing code:

class Art {

Art() {

System.out.println("Art constructor");

}

}

 

class Drawing extends Art {

Drawing() {

System.out.println("Drawing constructor");

}

}

 

public class Cartoon extends Drawing {

public Cartoon() {

System.out.println("Cartoon constructor");

}

public static void main(String[] args) {

Cartoon x = new Cartoon();

}

} ///:

Result:

    Art constructor

Drawing constructor

Cartoon constructor

Conclusion: base class is initialized before the derived-class constructors can access it.先初始化父类,保证了不会产生垃圾变量。

  1. Combining composition and inheritance

  • Name hiding

    Testing code:

class Homer {

char doh(char c) {

System.out.println("doh(char)");

return 'd';

}

float doh(float f) {

System.out.println("doh(float)");

return 1.0f;

}

}

 

class Milhouse {}

 

class Bart extends Homer {

void doh(Milhouse m) {

System.out.println("doh(Milhouse)");

}

/*char doh(char c) {

     System.out.println("doh(overload char)");

     return 'd';

     }*/

}

 

public class Hide {

public static void main(String[] args) {

Bart b = new Bart();

b.doh(1);

b.doh('x');

b.doh(1.0f);

b.doh(new Milhouse());

b.doh(null);

}

} ///:~

Conclusion:即使子类有相同的方法名,只要参数不同(如果参数相同,返回值相同就会覆盖父类的方法)。如果在c中必须写不同的函数,或者通过增加参数,SIZEOF来判断比java麻烦。

  1. Choosing composition vs. inheritance

    何时使用组合或者组合是挺复杂的一个问题,需要不断的实践才能慢慢体会。目前我的想法是如果使用了继承那么父类的方法全部暴露出来,父类和子类如果是一个包含的关系可以使用继承,如,Shape包含于rectangle。使用组合的话,父类和子类应该是一个组成的关系,如书中汽车的例子。如同书中说的Is-a还是Has-a的关系

  2. Protected

    Testing code:

import java.util.*;

 

class Villain {

private String name;

protected void set(String nm) { name = nm; }

public Villain(String name) { this.name = name; }

public String toString() {

return "I'm 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); // Available because it's protected

this.orcNumber = orcNumber;

}

public String toString() {

return "Orc " + orcNumber + ": " + super.toString();

}

public static void main(String[] args) {

Orc orc = new Orc("Limburger", 12);

System.out.println(orc);

orc.change("Bob", 19);

System.out.println(orc);

}

} ///:~

Conclusion:子类可以访问父类中的protected方法。注意return那行,代码非常简洁。

  1. Incremental development

One of the advantages of inheritance is that it supports incremental development. You can introduce new code without causing bugs in existing code; 的确如果是C代码没有继承,如何新的开发bug都比较难找。

  • Upcasting

    Testing code:

import java.util.*;

 

class Instrument {

public void play() {}

static void tune(Instrument i) {

// ...

i.play();

}

}

 

// Wind objects are instruments

// because they have the same interface:

public class Wind extends Instrument {

public static void main(String[] args) {

Wind flute = new Wind();

Instrument.tune(flute); // Upcasting

}

} ///:~

我对Upcasting的理解是最大可能的增加复用,减少重复敲代码。

  1. The final keyword

    Two reasos using final

  • Design
  • Efficiency

Three places where final can be used

  • Data
  • Methods
  • Classes

Final有点类似于c中的constant,对于一个对象的话final的使用相当于固定对象,但是对象的值可以变。像结婚一样,我只和你结婚,结婚后你怎么变无所谓。C中对应的好像指针常量(char * const)。

import java.util.*;

 

class Value {

int i; // Package access

public Value(int i) { this.i = i; }

}

 

public class FinalData {

private static Random rand = new Random();

private String id;

public FinalData(String id) { this.id = id; }

// Can be compile-time constants:

private final int VAL_ONE = 9;

private static final int VAL_TWO = 99;

// Typical public constant:

public static final int VAL_THREE = 39;

// Cannot be compile-time constants:

private final int i4 = rand.nextInt(20);

static final int i5 = rand.nextInt(20);

private Value v1 = new Value(11);

private final Value v2 = new Value(22);

private static final Value v3 = new Value(33);

// Arrays:

private final int[] a = { 1, 2, 3, 4, 5, 6 };

public String toString() {

return id + ": " + "i4 = " + i4 + ", i5 = " + i5

+ " a[0] = " + a[0] + ", a[1] = " + a[1];

}

public static void main(String[] args) {

FinalData fd1 = new FinalData("fd1");

//! fd1.VAL_ONE++; // Error: can't change value

fd1.v2.i++; // Object isn't constant!

fd1.v1 = new Value(9); // OK -- not final

for(int i = 0; i < fd1.a.length; i++)

fd1.a[i]++; // Object isn't constant!

//! fd1.v2 = new Value(0); // Error: Can't

//! fd1.v3 = new Value(1); // change reference

//! fd1.a = new int[3];

System.out.println(fd1);

System.out.println("Creating new FinalData");

FinalData fd2 = new FinalData("fd2");

System.out.println(fd1);

System.out.println(fd2);

}

} ///:~

Results:

fd1: i4 = 10, i5 = 10 a[0] = 2, a[1] = 3

Creating new FinalData

fd1: i4 = 10, i5 = 10 a[0] = 2, a[1] = 3

fd2: i4 = 9, i5 = 10 a[0] = 1, a[1] = 2

这个例子清晰的演示了object和primitive type 中final的区别。注意数组也是一个object的引用。

  • Blank final

Testing code:

 

class Poppet {

private int i;

Poppet(int ii) { this.i = ii; }

}

 

public class BlankFinal {

private final int i = 0; // Initialized final

private final int j; // Blank final

private final Poppet p; // Blank final reference

// Blank finals MUST be initialized in the constructor:

public BlankFinal() {

j = 1; // Initialize blank final

p = new Poppet(1); // Initialize blank final reference

}

public BlankFinal(int x) {

j = x; // Initialize blank final

p = new Poppet(x); // Initialize blank final reference

}

public static void main(String[] args) {

new BlankFinal();

new BlankFinal(47);

System.out.println();

}

}

Conclusion:如果final没有在定义时初始化,就必须在构造函数中初始化。把BlankFinal中对对象Poppet 的初始化注释掉会报错。

  • Final methods

    Two reasons for final methods:

  1. first is to put a "lock" on the method to prevent any inheriting class from changing its meaning.
  2. The second reason for final methods is efficiency

如果父类中的方法不想让子类继承,父类中用private可以达到效果,不过同一个Package下的其他类也不能访问了。

Final还可以用来修饰参数(同C)和class。Class修饰为final则不能继承。

  • Initialzation with inheritance

class Insect {

private int i = 9;

protected int j;

Insect() {

System.out.println("i = " + i + ", j = " + j);

j = 39;

}

private static int x1 =

print("static Insect.x1 initialized");

static int print(String s) {

System.out.println(s);

return 47;

}

}

 

public class Beetle extends Insect {

 

public Beetle() {

System.out.println("k = " + test);

System.out.println("j = " + j);

}

private int k = print("Beetle.k initialized");

private static int x2 =

print("static Beetle.x2 initialized");

public int test = print("Beetle.k initialized");

 

public static void main(String[] args) {

System.out.println("Beetle constructor");

Beetle b = new Beetle();

}

} ///:~

Result:

static Insect.x1 initialized

static Beetle.x2 initialized

Beetle constructor

i = 9, j = 0

Beetle.k initialized

Beetle.k initialized

k = 47

j = 39

Conslusion: 初始化时先会初始化父类的static变量,然后初始化构造函数,然后按照文本顺序进行变量的初始化。

  1. My thinking in java

    Overload:为了增加代码复用的一种方法,同时也降低了代码的负责度。我可以不管参数的变化,只需要调用相同的方法。好比去吃饭,我一个人去吃饭可以同样的点菜,几个人也是同样的点菜,这也相当于是一种重载了。

    继承:如果C中想要继承,那就相当于重新copy在修改了。非常不优雅。

    java用了Public,protected,private,可以让不必要的接口隐藏掉,看到该看到的。接着有了继承,还好只有单继承,不然是前进10步倒退了7步了,继承的设计我觉得挺难,什么该用protected,什么时候用private得好好思考。为了控制有些方法不能被继承,但是又能被同一Package下的类访问,发明了final methods,为了联系同一类型对象之间的联系,有了static。这些设计看起来还是蛮顺其自然的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值