8.多态--java笔记

1.绑定

定义:将一个方法调用同一个方法主体关联起来称作绑定。

前期绑定 就是在程序运行之间就知道调用哪个主体的方法。

例子:Shape是基类

public class Shape {
  public void draw() {}
  public void erase() {}
}

public class Circle extends Shape {
  public void draw() { print("Circle.draw()"); }
  public void erase() { print("Circle.erase()"); }
}

public class Triangle extends Shape {
  public void draw() { print("Triangle.draw()"); }
  public void erase() { print("Triangle.erase()"); }
}

---------
public void applyDraw(Shape shape){
      shape.draw();
}

applyDraw(new Circle());
此时shape.draw()在程序运行前不知道用哪个子类的draw。所以用后期绑定,后期绑定也是有某种类型信息在对象里面。

java中除了static和final(private方法也是final方法)其他方法都是后期绑定。static是静态,不和具体的对象实例联系。final是不想让其他覆盖,这是它第一个目的,还有就是在编译时直接插入到调用的位置,问题就是方法体长的效率反而低,所以使用final主要以第一个为选用标准。

2.覆盖私有方法的假象

public class PrivateOverride {
  private void f() { print("private f()"); }
  public static void main(String[] args) {
    PrivateOverride po = new Derived();
    po.f();
  }
}

class Derived extends PrivateOverride {
  public void f() { print("public f()"); }
} /* Output:
private f()
*///:~

因为private没有被覆盖,所以向上转型后使用的父类自己的f();

3.域和静态方法

public int field=0;

public static String method(){}

这两个在向上转型后都是使用父类的域和静态方法。 在此所有对域的访问通过编译器,也就是说在编译期间就能确定。静态方法只是与类连在一起,所以也是编译期间就可以确定.子类可以具有父类的可见(覆盖后)方法和域,总之,域和静态方法不具多态性。

只有普通方法的调用是多态的。

4.构造器和多态
构造器其实是隐式的static,不具备多态性,但是构造器的调用顺序还是要注意一下。
class Glyph {
  void draw() { print("Glyph.draw()"); }
  Glyph() {
    1.  print("Glyph() before draw()");
    draw();
    3.   print("Glyph() after draw()");
  }
}   

class RoundGlyph extends Glyph {
  private int radius = 1;
  RoundGlyph(int r) {
    radius = r;
 4.   print("RoundGlyph.RoundGlyph(), radius = " + radius);
  }
  void draw() {
   2.  print("RoundGlyph.draw(), radius = " + radius); 此时成员初始化还没执行,所以radius是0.
  }
}   
public class PolyConstructors {
  public static void main(String[] args) {
    new RoundGlyph(5);
  }
} /* Output:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
*///:~

构造顺序
1.任何事物发生之前,分配给对象的存储空间初始化成二进制的零。这个第二步radius为0的原因。
2.基类成员then基类构造器。
3.重复2。
4.导出类的成员then构造器。


5.协变返回类型

直接说它的含义有点绕,下面通过例子说明一下
class Mill {
  Grain process() { return new Grain(); }
}

class WheatMill extends Mill {
  Wheat process() { return new Wheat(); }
}
Wheat是Grain的一个导出类。
注意此时process的返回类型不一样。
Mill m= new WheatMill();
m.process返回的是Wheat。这就是协变返回,导出类WheatMill中覆盖的方法process可以返回基类方法process返回类型Grain的某种导出类型Wheat。
核心:这里process是覆盖的,因为返回类型Grain是Wheat的基类,这个条件很重要。
6.纯继承和扩展
老问题了,纯继承是is-a的关系,扩展时is-like-a的关系。

7.向下转型成某个导出类都要进行类型检查



<think>好的,我现在需要回答用户关于面向对象编程中“Has-a”关系的问题。首先,我需要确认自己对“Has-a”关系的理解是否正确。根据所学知识,“Has-a”关系通常指的是组合(Composition)或聚合(Aggregation),即一个类包含另一个类的实例作为其成员。这与“Is-a”关系(继承)不同,后者是子类与父类的关系。 接下来,我需要确保引用的资料是否相关。用户提供的引用中有几个关于继承和类结构的,比如引用[1]提到多重继承的语法,这可能与组合有关联,但需要确认。其他引用如[2]和[3]涉及Java中的数组存储和字符串处理,可能与当前问题无关,但引用[1]中的多重继承可能与组合形成对比,所以可能需要参考。 然后,我要列出正确的关于“Has-a”关系的陈述。可能的正确点包括:表示对象之间的包含关系、通过成员变量实现、支持代码复用而不使用继承、具有更强的封装性,以及生命周期可能由包含类控制(组合的情况)。 同时,错误的观点需要指出,比如与继承混淆、动态多态的实现方式,或者必须使用接口的说法,这些都是不正确的。 需要检查每个引用是否支持这些观点。例如,引用[1]讨论的是继承声明,可能用来对比“Has-a”与继承的不同。其他引用可能没有直接关联,但需要确保不错误引用。 最后,生成相关问题时要围绕“Has-a”关系的定义、实现方式、与组合聚合的区别、优缺点和应用场景展开,确保问题有助于用户深入理解。</think>在面向对象编程中,“Has-a”关系描述的是对象之间的组合或聚合关系。以下是关于“Has-a”关系的正确描述: 1. **表示对象包含关系** “Has-a”关系表示一个类包含另一个类的实例作为其成员变量。例如,汽车类包含引擎类: ```java class Engine { /*...*/ } class Car { private Engine engine; // Car "has-a" Engine } ``` 这种关系通过成员变量直接实现[^1]。 2. **支持代码复用而不依赖继承** 与继承的“Is-a”关系不同,“Has-a”通过组合其他类的功能实现复用,避免了继承层级过深的问题。例如,笔记本电脑类可以包含电池、屏幕等组件,而非通过继承实现功能扩展。 3. **体现更强的封装性** 包含对象的内部状态由外层类控制,外部无法直接访问被包含对象。例如: ```java class Library { private List<Book> books; // 外部无法直接修改books列表 } ``` 4. **生命周期依赖(组合场景)** 在严格组合关系中,被包含对象的生命周期由其容器类控制。当容器对象销毁时,被包含对象也会随之销毁。例如: ```python class Brain: pass class Human: def __init__(self): self.brain = Brain() # Brain与Human同生共死 ``` 5. **灵活替换实现(聚合场景)** 在聚合关系中,被包含对象可以独立存在且支持动态替换。例如购物车可以包含多个商品,但商品可以独立于购物车存在: ```java class ShoppingCart { private List<Product> products; // 可随时添加/移除商品 } ``` ### 常见错误观点辨析 - ❌ “Has-a关系通过继承实现” → 继承属于“Is-a”关系 - ❌ “用于实现动态多态” → 多态主要通过继承和接口实现 - ❌ “必须使用接口定义” → 可以直接包含具体类实例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值