一:合成的语法
1.定义:一个类由不同对象类型组成
2.实例
public class Six {
public static void main(String[] args) {
Six six = new Six();
System.out.println(six.classB.a);
System.out.println(six.classB.str);
System.out.println(six.classB.classA.a);
System.out.println(six.classB.classA.str);
}
//这一部分是为了能在main中访问classB
private ClassB classB;
private Six(){
this.classB = new ClassB();
}
private class ClassA{
int a = 1;
String str = "我是classA";
}
private class ClassB{
ClassA classA = new ClassA();
int a = 2;
String str = "我是classB";
}
}
3.说明
类 | 组成 |
---|---|
classA | int + str |
classB | classA + int + str |
Six | classB |
二:继承的语法
0.前言
作用域 | 当前类 | 同一package | 子孙类 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
friendly(default) | √ | √ | × | × |
private | √ | × | × | × |
1.定义:可以从 动物 和 狗,猫,老鼠的角度去理解
2.实例(包含了①public 覆盖 ②protected覆盖 ③public 直接调用 ④protected直接调用 ⑤protected间接调用 ⑥构造函数覆盖)
<1>同一个包下 可以访问protected
class Animal
package one;
public class Animal{
protected int age;
protected int weight;
protected int height;
public Animal(int age, int weight, int height){
this.age = age;
this.weight = weight;
this.height = height;
}
public void angryVoice(){
System.out.println("啊啊啊啊啊");
}
public void sleepVoice(){
System.out.println("啊啊啊啊啊");
}
protected String getMyInfo(){
return "我的年龄=" + age + " 我的体重=" + age + " 我的身高=" + height;
}
public void sayMyInfo(){
System.out.println(getMyInfo());
}
}
class Lion
package one;
public class Lion extends Animal{
public Lion(){
super(10, 100, 100);
}
public Lion(int age, int weight, int height) {
super(age, weight, height);
}
@Override
public void sleepVoice() {
System.out.println("吼吼吼吼吼");
}
@Override
protected String getMyInfo() {
return "我是狮子 " + super.getMyInfo();
}
protected void test(){
System.out.println("wewewe");
}
}
演示代码
package one;
public class Six {
public static void main(String[] args) {
Lion lion = new Lion(10, 100, 100);
lion.sleepVoice();
System.out.println(lion.getMyInfo());
}
}
输出
吼吼吼吼吼
我是狮子 我的年龄=10 我的体重=10 我的身高=100
Process finished with exit code 0
<2>不同包下不能访问protected
演示代码
public static void main(String[] args) {
Lion lion = new Lion(10, 100, 100);
lion.sleepVoice();
lion.sayMyInfo();
}
输出
吼吼吼吼吼
我是狮子 我的年龄=10 我的体重=10 我的身高=100
Process finished with exit code 0
三:选择合成还是继承 以及final
1.书本原话---再论合成与继承
在面向对象的程序设计中,创建和使用代码最可能采取的一种做法是:将数据和方法统一封装到一个类里,并且使用那个类的对象。有些时候,需通过“合成”技术用现成的类来构造新类。而继承是最少见的一种做法。因此,尽管继承在学习OOP 的过程中得到了大量的强调,但并不意味着应该尽可能地到处使用它。相反,使用它时要特别慎重。只有在清楚知道继承在所有方法中最有效的前提下,才可考虑它。为判断自己到底应该选用合成还是继承,一个最简单的办法就是考虑是否需要从新类上溯造型回基础类。若必须上溯,就需要继承。但如果不需要上溯造型,就应提醒自己防止继承的滥用。在下一章里(多形性),会向大家介绍必须进行上溯造型的一种场合。但只要记住经常问自己“我真的需要上溯造型吗”,对于合成还是继承的选择就不应该是个太大的问题。
2.我的解读
①使用频率:
最常见:将数据和方法统一封装到一个类里,并且使用那个类的对象----(自行构造)
有时候:需通过“合成”技术用现成的类来构造新类----(合成)
最少见:而继承是最少见的一种做法----(继承)
②强调点:
尽管在面向对象中大量强调继承,但并不意味着应该尽可能地到处使用它,要慎重
③使用时想想:
问自己:是不是继承真的是最合适的方法,我真的需要吗,
3.final
①final数据
- 常数 永远不会改变
- 不希望它变化
- 可以编译的时候就封装到计算过程里,节省了运行时候的成本
演示
package one;
public class Six {
public static void main(String[] args) {
//直接赋值
final int a = 100;
//初始化为空,但是在使用前要赋值
final int b;
b = 100;
System.out.println("a = " + a);
System.out.println("b = " + b);
say("final参数");
}
//参数不能改变了
public static void say(final String string){
System.out.println(string);
}
}
②final方法
使用理由
- 提高效率
- 不想被继承改变
使用方式
- 代码直接插入
使用时
- 尽量避免使用
Java 编译器能自动侦测这些情况,并颇为“明智”地决定是否嵌入一个 final 方法。然而,最好还是不要完全相信编译器能正确地作出所有判断。通常,只有在方法的代码量非常少,或者想明确禁止方法被覆盖的时候,才应考虑将一个方法设为final。
③final类
说明
如果说整个类都是 final(在它的定义前冠以 final 关键字),就表明自己不希望从这个类继承,或者不允许其他任何人采取这种操作。换言之,出于这样或那样的原因,我们的类肯定不需要进行任何改变;或者出于安全方面的理由,我们不希望进行子类化(子类处理)。除此以外,我们或许还考虑到执行效率的问题,并想确保涉及这个类各对象的所有行动都要尽可能地有效。
注意
将类定义成 final 后,结果只是禁止进行继承——没有更多的限制。然而,由于它禁止了继承,所以一个 final 类中的所有方法都默认为 final。因为此时再也无法覆盖它们。所以与我们将一个方法明确声明为final 一样,编译器此时有相同的效率选择。
可为final 类内的一个方法添加final 指示符,但这样做没有任何意义。
final 注意事项
设计一个类时,往往需要考虑是否将一个方法设为 final。可能会觉得使用自己的类时执行效率非常重要,没有人想覆盖自己的方法。这种想法在某些时候是正确的。
但要慎重作出自己的假定。