【问题标题】:Why is the compiler allowing the variable of class "I" to be assigned an object of class "N" which inherits the "I" class为什么编译器允许将类“I”的变量分配给继承“I”类的“N”类对象
【发布时间】:2015-05-29 23:51:13
【问题描述】:
class I {    
    String s="yes its me:I";

    void Mine(){
            System.out.println(s);
    }
}

class N extends I {
    String l="yes its me:N";

    void Mine(){
        System.out.println(l);
    }   
}


class T extends N{
    String m="yes its me:T";
    void Mine(){
        System.out.println(m);
    }
}

class Test{
    public static void main(String[] args) {
        I i=new I();
        N n=new N();
        T t=new T();
        I r; // r is a variable of class type I

        r=i; // fine here

        r.Mine(); //no doubt here

        r=n; // heres the problem

        r.Mine(); // these are working only 

        r=t; //with overriding methods existing & no other method exists in all classes

        r.Mine();
    }
}

另外请告诉我:如果我们声明一个类类型的变量,它会做什么(我的意思是它会通过类的方法和实例变量的数量来识别,还是仅通过方法或仅实例变量来识别)。

【问题讨论】:

  • 因为这就是继承的意思。 N 可以在任何需要I 的地方使用。
  • 但是当我们向 N 添加一个新方法并编译它然后它显示错误时不能使用...感谢答案和 cmets
  • 显示什么错误?这是另一个问题吗?
  • 你能把最后一个问题解释清楚一点吗?

标签: java class variables types


【解决方案1】:
class Vehicle {
    Engine myEngine = new Engine();
    void start() {
        myEngine.start();
    }
    void stop() {
        myEngine.stop();
    }
}
class VehicleWithSteering extends Vehicle {
    Steering mySteering = new Steering();
    void start() {
        mySteering.reset();
        myEngine.start();
    }
    void steerLeft() {
        mySteering.left();
    }
    void steerRight() {
        mySteering.right();
    }
}

如您所见,VehicleWithSteering 确实有基本的Vehicle 没有的方法。它还覆盖了void start() 方法,因为启动这个更复杂的车辆涉及不同的例程。

class NoviceDriver {
    Vehicle myVehicle;
    public NoviceDriver(Vehicle vehicle) {
        myVehicle = vehicle;
    }
    void doSomething() {
        myVehicle.start();
        myVehicle.stop();
    }
}
class AdvancedDriver {
    VehicleWithSteering myVehicle;
    public NoviceDriver(VehicleWithSteering vehicle) {
        myVehicle = vehicle;
    }
    void doSomethingElse() {
        myVehicle.start();
        myVehicle.steerLeft();
        myVehicle.stop();
    }
}

AdvancedDriver 需要基本Vehicle 无法满足的附加功能,因此它始终需要VehicleWithSteering 的实例。

class Test{
    public static void main(String[] args) {
        // Create one basic vehicle
        Vehicle a = new Vehicle();
        // And one more advanced
        VehicleWithSteering b = new VehicleWithSteering();

        // A novice driver is satisfied with having a basic vehicle
        NoviceDriver x = new NoviceDriver(a);

        // The advanced driver however needs more functionality
        AdvancedDriver y = new AdvancedDriver(b);

        // A novice driver can use the advanced vehicle as well
        // But he will not bother about the advanced functionality
        NoviceDriver z = new NoviceDriver(b);
    }
}

NoviceDriver 只知道如何访问Vehicle 的方法。但由于VehicleWithSteering 中也存在这些方法,因此他也可以使用该方法。 NoviceDriver 甚至不知道转向意味着什么,所以他不会触摸任何他不知道的控件。

AdvancedDriver 不能与 Vehicle 配合使用,因为它不包含所需的转向方法。

如果对 VehicleWithSteering 进行更高级的改进,NoviceDriverAdvancedDriver 仍然可以使用它来执行其有限的任务,因为它仍然提供所需的基本功能。

NoviceDriver 可以访问原始Vehicle 拥有的所有公共方法和属性。它不知道以后添加的新方法或属性。在这种情况下,它可以看到VehicleWithSteering 上继承的Engine myEngine 属性,但看不到新的Steering mySteering 属性。

至于你的最后一个问题:这取决于语言。

在 Java 中,每个类都有一个其他继承类和它实现的接口的内部列表。每当您将细化转换为更原始的类型时,Java 都会检查原始类型是否在列表中。这种行为也用于其他严格类型的语言,例如 C++、C# 和许多其他语言。

另一种概念是 Duck-Typing。

当我看到一只像鸭子一样走路,像鸭子一样游泳,像鸭子一样叫的鸟时,我称那只鸟为鸭子。

当一种语言使用 Duck-Typing 时,它会通过名称和签名在对象中查找请求的方法。这可能发生在编译时或运行时,在后一种情况下,大多数支持 Duck-Typing 的语言都会引发异常。

一些语言,如 PHP 和其他各种脚本语言都具有严格的类型检查和 Duck-Typing。这意味着您既可以选择对继承的类列表和实现的接口强制执行严格的类型检查,也可以在省略该检查时默认使用 Duck-Typing。

【讨论】:

    【解决方案2】:

    考虑:

    class MP3Player // any MP3 player
    class IPod extends MP3Player // an iPod MP3 player
    class IPodClassic extends IPod // an iPod Classic in particular
    

    然后:

    MP3Player m = new IPod();
    m.playMp3();
    

    是允许的,因为 iPod 是 MP3 播放器,可以做任何 MP3 播放器可以做的事情。

    IPod i = new MP3Player(); // Not allowed
    i.showAppStore(); // MP3Player might not have app store
    

    不允许,因为并非所有 MP3 播放器都是 iPod。

    IPodClassic ic = new IPod(); // Not allowed
    ic.getHardDisk(); // Not all iPod objects have a hard disk.
    

    不允许,因为并非所有 iPod 都是 iPod 经典。

    【讨论】:

      猜你喜欢
      • 2021-10-21
      • 2017-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-08
      相关资源
      最近更新 更多