【问题标题】:Parent class define static class for child class父类为子类定义静态类
【发布时间】:2021-03-22 05:41:07
【问题描述】:

想知道在 Java 中是否有办法做到这一点。

想象一下,我想创建一个父类(可能是抽象的)并创建多个不同的子类。我希望所有类都有一个特定的字段,但我需要该字段在子上下文中是静态的。有没有办法可以在父类中定义它?

例如,假设我有用于名为 Foo 的字段的 getter 和 setter。在父类中,静态字段被初始化为字符串“foo”。我有两个子类 AbsChildOne 和 AbsChildTwo。我想做的是:

    AbsChildOne absOneA = new AbsChildOne();
    AbsChildOne absOneB = new AbsChildOne();
    AbsChildTwo absTwo = new AbsChildTwo();

    absOneA.setFoo("bar");
    System.out.println("absOneB "+absOneB.getFoo());
    System.out.println("absTwo "+absTwo.getFoo());

返回

absOne2 bar
absTwo foo

也就是说,静态字段只对子类是静态的,对其他子类没有。

【问题讨论】:

  • 一个简单的问题,为什么需要一个实例 (new) 和一个方法来设置一个 static 字段?想知道你是否很清楚static 的意图是什么......
  • @TraianGEICU 我需要静态处于子类级别,因为我使用的是 JUnit,它为类中的每个测试方法重新实例化测试类,并且我计划使用相同的父类用于多个多方法测试类。如果静态留在父类中,它将“渗入”其他子类,这是不可取的。最后,我只为 getter 方法做子类静态和自定义接口来“强制”它们的存在。
  • 回想起来,我认为清除静态父字段的静态 @beforeclass 方法会起作用......但我认为这仍然必须在子类中实现。
  • 继承静态字段对您的目的毫无用处,因为无论来自何处,所有实例/子类/父级始终为 1 值。更新。只需查看详细的答案,看看是否可能对您有用。另一种选择是考虑重新设计测试用例......(重点是尽量保持代码,测试用例尽可能简单)

标签: java class inheritance static abstract


【解决方案1】:

事实上,static 是类级别的,因此每个 classes 包括 subclasses 每次都会有一个值(不要与类实例混淆)。所以在使用静态(甚至初始化)时不需要有实例。(new)

String s_get_static_value = ClassName.value。对于每个ClassName_instances,每次只有一个值适用于所有instances。所以一旦改变(在类级别,实例)将反映到所有实例(隐含类级别)。

关键是你不能保留从同一个静态派生的 2 个单独的静态(总是有 1 个值而不是 2)。

现在,如果想要有一个扩展字段父级,每个子级具有单独的值(并且在类级别只有 1 个,并且所有实例都派生自 TypeType 也可以是一个不同的子类。@987654330 @ 与 Child_type 不同,即使 Child 扩展了 Parent )。

考虑一下逻辑。(要求:与您的相同,但没有静态)

//in term of field_value ; all in the same time and just 1 based on Types
parent = A (on Parent class) : Type Parent
parent = A1 (on Child1 at inhereted field from Parent) : Type Child1 
parent = A2 (on Child2 at inhereted field from Parent) : Type Child2

//oneInstance is doing that task which is an object based on Singleton
//can hold as may parameters as wanted (mystring in this case)   

也许这对你有帮助。

//adjusted singleton with a map which hold instances
import java.util.HashMap;

import tst.Test02.Child1;
import tst.Test02.Child2;

public class OneInstance 
{
    String myString = "";
    private OneInstance oi ;
    public static HashMap<String, OneInstance> hm = new HashMap<String,OneInstance>();
    public static OneInstance getInstance(Object o)
    {
        if(!hm.containsKey(o.getClass().toString()))
            hm.put(o.getClass().toString(), new OneInstance("default value for _"+o.getClass().toString()));
        return hm.get(o.getClass().toString());
        
    }
    public static OneInstance getInstance(Object o,String s)
    {
        if(!hm.containsKey(o.getClass().toString()))
            hm.put(o.getClass().toString(), new OneInstance(s));
        return hm.get(o.getClass().toString());
        
    }
    public static OneInstance getInstance()
    {
        if(!hm.containsKey(new Parent().getClass().toString()))
            hm.put(new Parent().getClass().toString(), new OneInstance("default value for Parent"));
        return hm.get(new Parent().getClass().toString());
    }
    
    private OneInstance() {}
    private OneInstance(String s)
    {
        
        myString = s;
    }
    
}

public class Parent 
{
    static MyObj sobj = new MyObj("static name");
    OneInstance oi;
    
    public String toString()
    {
        return "myString="+oi.getInstance().myString;
    }
}

//usage
import java.util.Set;

public class Test02 
{
    public static void main(String[] args)
    {
        Test02 t = new Test02();
        Child1 c1;
        Child2 c2;
        System.out.println("inhereted name for child1:"+Child1.sobj.name);
        Child1.sobj.name = "child1_new_name";
        System.out.println("child1 new name:"+Child1.sobj.name);
        System.out.println("inhereted name for child2:"+Child2.sobj.name);
        System.out.println("-----------");
        System.out.println(new Parent());
        c1 = t.new Child1("child1_string");
        
        //with any specification just init with parent value and keep
        System.out.println(c1);
        System.out.println(c1.oi.getInstance(c1).myString);
        System.out.println("-----------");
        
        System.out.println("dump HashMap");
        OneInstance.hm.forEach((k, v) -> System.out.println((k + ":" + v.myString)));
        System.out.println("-----------");
        c2 = t.new Child2("child2_string from constructor"); 
        c1.oi.getInstance(c1).myString = "changed for child 1";
        System.out.println(c1.oi.getInstance(c1).myString);
        System.out.println("dump HashMap");
        OneInstance.hm.forEach((k, v) -> System.out.println((k + ":" + v.myString)));
        System.out.println("-----------");
        c2 = t.new Child2("child2_string from constructor"); 
        System.out.println(c2);
        
        //System.out.println(c2.oi.getInstance(c2).myString);
        //c2.oi.getInstance(c2).myString = "changed for child 2";
        //System.out.println(c2.oi.getInstance(c2).myString);
        
        System.out.println(c1);
        System.out.println(c1.oi.getInstance(c1).myString);
        System.out.println(c2.oi.getInstance(c2).myString);
        System.out.println("dump HashMap");
        OneInstance.hm.forEach((k, v) -> System.out.println((k + ":" + v.myString)));
        System.out.println("-----------");
        
        
    }
    
    class Child1 extends Parent
    {
         //inherited
         //OneInstance oi ;
         Child1(String s)
         {
             oi = OneInstance.getInstance(this, s);
         }
         public String toString()
         {
            return "myString="+oi.getInstance(this).myString;
         }
    }
    
    class Child2 extends Parent
    {
         //OneInstance oi ;
         Child2(String s)
         {
             oi =OneInstance.getInstance(this, s);
         }
         public String toString()
         {
            return "myString="+oi.getInstance(this).myString;
         }
    }
}

输出:

inhereted name for child1:static name
child1 new name:child1_new_name
inhereted name for child2:child1_new_name
-----------
myString=default value for Parent
myString=child1_string
child1_string
-----------
dump HashMap
class tst.Test02$Child1:child1_string
class tst.Parent:default value for Parent
-----------
changed for child 1
dump HashMap
class tst.Test02$Child1:changed for child 1
class tst.Test02$Child2:child2_string from constructor
class tst.Parent:default value for Parent
-----------
myString=child2_string from constructor
myString=changed for child 1
changed for child 1
child2_string from constructor
dump HashMap
class tst.Test02$Child1:changed for child 1
class tst.Test02$Child2:child2_string from constructor
class tst.Parent:default value for Parent
-----------

关于测试,之前是代码开发。如果代码中存在逻辑错误,那么测试会发生什么? (整个测试套件将失败,并且在能够继续之前需要解决一些关键缺陷......) 很高兴知道测试 api_junit 的各种设置,但这不是主要范围。代码设计可以正常运行,而不是用于测试目的的代码设计。 (主要问题来自代码设计static 而不是来自how to test

注意:您必须添加一些逻辑来根据继承进行调整(保留该字段),但为什么不更改逻辑并允许为子项设置另一个不同的字段? 它会很容易实现,也可以使用静态。

class Parent 
{
   static String parent;
}
class Child1 extends Parent 
{
   //inhereted
   //static String parent;

   //add a new one per subclasses
   static String child1;
}

只需比较每个场景所需的代码行,然后询问是否真的值得?指标(甚至在代码行内)也计入质量代码。

【讨论】:

  • 澄清一下,我不编写应用程序代码,我为其他应用程序编写测试代码。我开始认为我必须有一个在子类上键入的静态映射,正如您在此处所建议的那样。我觉得我应该能够做类似class Parent { public void getStatic() { System.out.println(this.getClass().&lt;static field name&gt;); } } 的事情如果从子类class ChildA extends Parent 的对象调用它会给我 ChildA 类的静态,同样从另一个子类 ChildB 给我 ChildB 的静态类。
  • 您的责任方没有问题。问题是相关的开发(如何做某事),简短的回答是你不能使用静态。现在如果想测试其他东西。(但即使在这里你也不能通过语言能力)。因此,即使使用继承的静态字段测试初始想法也无法正常工作(即使使用小技巧也可能会一团糟)。关于在子类/obj 上使用带有键的静态映射可以工作(由您决定如何编写 TC,但即使在这里编写 TC_scripts 也不涉及通过代码设计:即使开发人员/测试人员也一样工作
  • Script TC design (java with junit等)和software-dev一样,dev概念不变,要指出来。
  • 这里的诀窍是使用一个对象作为参数(这样可以保存尽可能多的其他参数)并使用 Map 来保存各种实例类型(主要是一个类型的 1 个实例)......如果认为对你有用,使用它......(但首先运行小测试以确保你得到预期的输出)
  • 我提出这是一个测试来解释我的范围完全是 JUnit,这就是为什么需要静态使用;为了在类中的方法之间共享数据点,它们需要是静态的。这让我意识到我们可能应该使用其他东西,但这个决定有点晚了。
猜你喜欢
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 2020-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多