3

ずっと気になっていたので、聞いてみようと思いました。

私が書くなら

import java.util.*;
import java.lang.*;

class Main
{
    public static void main (String[] args) throws java.lang.Exception
    {
            new Shape();
            new Triangle();
    }

    public static class Shape
    {
            static String name = "shape";

            Shape()
            {
                    printName();
            }

            public void printName()
            {
                    System.out.println( name() );
            }

            public String name()
            {
                    return name;
            }
    }

    public static class Triangle extends Shape
    {
            static String name = "triangle";

            public String name()
            {
                    return name;
            }
    }
}

出力は

shape
triangle

でも書いたら

import java.util.*;
import java.lang.*;

class Main
{
    public static void main (String[] args) throws java.lang.Exception
    {
            new Shape();
            new Triangle();
    }

    public static class Shape
    {
            static String name = "shape";

            Shape()
            {
                    printName();
            }

            public void printName()
            {
                    System.out.println( name );
            }

    }

    public static class Triangle extends Shape
    {
            static String name = "triangle";
    }
}

出力は

shape
shape

最初のバージョンでは、同じ関数 getName() をすべてのサブクラスに何度もコピー アンド ペーストする必要がありました。もっと良い方法があるはずです。2 番目の例で何を変更する必要がありますか?

4

4 に答える 4

5

static フィールドは親クラスからアクセスできません。クラスはクラスの static フィールドをShape「認識」せず、独自の static フィールドを使用します。nameTrianglename

UPD:あなたは尋ねます: 2 番目の例で何を変更する必要がありますか? より具体的には、最初の例は、2 番目の例の正しい「修正」です。唯一の正しい方法は、メソッドのようなゲッター メソッドを使用するname()ことです。

UPD2: (私の解説から): ええと、別の方法: どんな種類のフィールドについても許してくださいname。代わりに、name()各クラスで必要な名前を返すメソッド (静的ではない!) を使用してください。ちょうどreturn "shape";またはreturn "triangle"それらの中で。

于 2013-01-09T19:35:33.933 に答える
1

さて、私はすでにこの質問に否定的な方法で答えました。しかし、一種の冗談で面白い解決策として (これはうまくいきます!!! )、printName()メソッドを次のように変更できます。

public void printName() throws NoSuchFieldException, IllegalAccessException {
    System.out.println((String)(this.getClass().getDeclaredField("name").get(this)));
}

これは、出力を得るために2 番目の例で行う必要がある変更の 1 つにすぎません。

shape
triangle
于 2013-01-09T20:10:34.567 に答える
0

これは、Java が名前を値に解決する方法をよく表しています。と呼ばれる 2 つの変数がありname、1 つは にShape、もう 1 つは にありTriangleます。Triangleはこれらのサブクラスですが、まったくShape 関連のない変数です。これは静的であるためです。静的なものは、オブジェクトではなくクラスに属しているため、オーバーライドされることはありません。Shapeで を参照する場合、これnameは実際には の省略形ですShape.name。同様に、 はTrianglename意味しTriangle.nameます。同じ記号は、異なるスコープ異なる変数を参照します。

このコードでは:

public class Shape {
    static String name = "shape";

    public static void main(String[] args) {
        System.out.println(name);
    }
}

class Colour {
    static String name = "colour";
}

出力が「色」になるとは一瞬も思わないでしょうか?これはまさにあなたが示すコードの状況です。2 つのクラス間の継承関係は、単なるおせっかいです。

名前をポリモーフィックにしたい場合、唯一のオプションはインスタンス メソッドを使用することです。これは、インスタンス メソッドがポリモーフィックにできる唯一のものであるためです。これを行う最も簡潔な方法は、定数をメソッドにインライン化することです。

class Main {

    public static void main(String[] args) {
        new Shape();
        new Triangle();
    }

    public static class Shape {
        Shape() {
            printName();
        }

        public void printName() {
            System.out.println(name());
        }

        public String name() {
            return "shape";
        }
    }

    public static class Triangle extends Shape {
        @Override
        public String name() {
            return "triangle";
        }
    }
}
于 2013-01-09T20:03:19.297 に答える
0

最終フィールドを使用してコンストラクターで設定することもできますが、ゲッターをオーバーライドすることをお勧めします。

public static class Shape
{
        protected final String name;

        public Shape()
        {
                this("shape");
        }

        protected Shape(String name)
        {
                this.name = name;
        }

        public void printName()
        {
                System.out.println( name() );
        }

        public String name()
        {
                return name;
        }
}

public static class Triangle extends Shape
{
        public Triangle()
        {
               super("triangle");
        }
}
于 2013-01-09T20:14:53.323 に答える